<commit_before>//! Json String Literal Generator
//!
//! Write json with Rust syntax instead of hard to read inline strings.
//! This crate doesn't evaluate any expressions, it just converts a Rust _token tree_ into a
//! minified json string.
//!
//! # Usage
//!
//! This crate is on [crates.io](https://crates.io/crates/json_str).
//!
//! There are two ways to reference `json_str` in your projects, depending on whether you're on
//! the `stable`/`beta` or `nightly` channels.
//!
//! ## Stable
//!
//! To get started, add `json_str` to your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! json_str = "*"
//! ```
//!
//! And reference it in your crate root:
//!
//! ```ignore
//! #[macro_use]
//! extern crate json_str;
//! ```
//!
//! ## Nightly
//!
//! To get started, add `json_str` to your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! json_str = { version = "*", features = "nightly" }
//! ```
//!
//! And reference it in your crate root:
//!
//! ```ignore
//! #![feature(plugin)]
//! #![plugin(json_str)]
//! ```
//!
//! If you're on the `nightly` channel, it's better to use the above `plugin` version with the `nightly`
//! feature because the conversion and sanitisation takes place at compile-time instead of runtime,
//! saving precious runtime cycles.
//!
//! ## Examples
//!
//! The `json_str!` macro will take an inline token tree and return a sanitised json `String`:
//!
//! ```
//! # #![feature(plugin)]
//! # #![plugin(json_str)]
//! # fn main() {
//! let json = json_str!({
//! 	"query": {
//! 		"filtered": {
//! 			"query": {
//! 				"match_all": {}
//! 			},
//! 			"filter": {
//! 				"geo_distance": {
//! 					"distance": "20km",
//! 					"location": {
//! 						"lat": 37.776,
//! 						"lon": -122.41
//! 					}
//! 				}
//! 			}
//! 		}
//! 	}
//! });
//! # }
//! ```
//!
//! This will also work for unquoted keys for something a bit more `rusty`:
//!
//! ```
//! # #![feature(plugin)]
//! # #![plugin(json_str)]
//! # fn main() {
//! let json = json_str!({
//! 	query: {
//! 		filtered: {
//! 			query: {
//! 				match_all: {}
//! 			},
//! 			filter: {
//! 				geo_distance: {
//! 					distance: "20km",
//! 					location: {
//! 						lat: 37.776,
//! 						lon: -122.41
//! 					}
//! 				}
//! 			}
//! 		}
//! 	}
//! });
//! # }
//! ```
//!
//! On `nightly`, there's an additional plugin called `json_lit` that returns a `&'static str`
//! instead of a `String`, so you can avoid allocating each time. The syntax is otherwise the same
//! as `json_str`:
//!
//! ```
//! # #![feature(plugin)]
//! # #![plugin(json_str)]
//! # fn main() {
//! let json = json_lit!({
//! 	"query": {
//! 		"filtered": {
//! 			"query": {
//! 				"match_all": {}
//! 			},
//! 			"filter": {
//! 				"geo_distance": {
//! 					"distance": "20km",
//! 					"location": {
//! 						"lat": 37.776,
//! 						"lon": -122.41
//! 					}
//! 				}
//! 			}
//! 		}
//! 	}
//! });
//! # }
//! ```
//!
//! For json values that can't be fully determined at compile-time,
//! use [json_macros](https://github.com/tomjakubowski/json_macros) instead.

#![doc(html_root_url = "http://kodraus.github.io/rustdoc/json_str/")]
#![cfg_attr(feature = "nightly", crate_type="dylib")]
#![cfg_attr(feature = "nightly", feature(plugin_registrar, rustc_private, quote, plugin, stmt_expr_attributes))]

#[doc(hidden)]
pub mod parse;

#[cfg(feature = "nightly")]
include!("lib.rs.in");

#[cfg_attr(not(feature = "nightly"), macro_export)]
#[cfg(not(feature = "nightly"))]
macro_rules! json_str {
	($j:tt) => ({
		let json_raw = stringify!($j);
		let mut json = String::with_capacity(json_raw.len());
		$crate::parse::sanitise(json_raw.as_bytes(), &mut json);

		json
	})
}
<commit_msg>ignore doc code<commit_after>//! Json String Literal Generator
//!
//! Write json with Rust syntax instead of hard to read inline strings.
//! This crate doesn't evaluate any expressions, it just converts a Rust _token tree_ into a
//! minified json string.
//!
//! # Usage
//!
//! This crate is on [crates.io](https://crates.io/crates/json_str).
//!
//! There are two ways to reference `json_str` in your projects, depending on whether you're on
//! the `stable`/`beta` or `nightly` channels.
//!
//! ## Stable
//!
//! To get started, add `json_str` to your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! json_str = "*"
//! ```
//!
//! And reference it in your crate root:
//!
//! ```ignore
//! #[macro_use]
//! extern crate json_str;
//! ```
//!
//! ## Nightly
//!
//! To get started, add `json_str` to your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! json_str = { version = "*", features = "nightly" }
//! ```
//!
//! And reference it in your crate root:
//!
//! ```ignore
//! #![feature(plugin)]
//! #![plugin(json_str)]
//! ```
//!
//! If you're on the `nightly` channel, it's better to use the above `plugin` version with the `nightly`
//! feature because the conversion and sanitisation takes place at compile-time instead of runtime,
//! saving precious runtime cycles.
//!
//! ## Examples
//!
//! The `json_str!` macro will take an inline token tree and return a sanitised json `String`:
//!
//! ```ignore
//! let json = json_str!({
//! 	"query": {
//! 		"filtered": {
//! 			"query": {
//! 				"match_all": {}
//! 			},
//! 			"filter": {
//! 				"geo_distance": {
//! 					"distance": "20km",
//! 					"location": {
//! 						"lat": 37.776,
//! 						"lon": -122.41
//! 					}
//! 				}
//! 			}
//! 		}
//! 	}
//! });
//! ```
//!
//! This will also work for unquoted keys for something a bit more `rusty`:
//!
//! ```ignore
//! let json = json_str!({
//! 	query: {
//! 		filtered: {
//! 			query: {
//! 				match_all: {}
//! 			},
//! 			filter: {
//! 				geo_distance: {
//! 					distance: "20km",
//! 					location: {
//! 						lat: 37.776,
//! 						lon: -122.41
//! 					}
//! 				}
//! 			}
//! 		}
//! 	}
//! });
//! ```
//!
//! On `nightly`, there's an additional plugin called `json_lit` that returns a `&'static str`
//! instead of a `String`, so you can avoid allocating each time. The syntax is otherwise the same
//! as `json_str`:
//!
//! ```ignore
//! let json = json_lit!({
//! 	"query": {
//! 		"filtered": {
//! 			"query": {
//! 				"match_all": {}
//! 			},
//! 			"filter": {
//! 				"geo_distance": {
//! 					"distance": "20km",
//! 					"location": {
//! 						"lat": 37.776,
//! 						"lon": -122.41
//! 					}
//! 				}
//! 			}
//! 		}
//! 	}
//! });
//! ```
//!
//! For json values that can't be fully determined at compile-time,
//! use [json_macros](https://github.com/tomjakubowski/json_macros) instead.

#![doc(html_root_url = "http://kodraus.github.io/rustdoc/json_str/")]
#![cfg_attr(feature = "nightly", crate_type="dylib")]
#![cfg_attr(feature = "nightly", feature(plugin_registrar, rustc_private, quote, plugin, stmt_expr_attributes))]

#[doc(hidden)]
pub mod parse;

#[cfg(feature = "nightly")]
include!("lib.rs.in");

#[cfg_attr(not(feature = "nightly"), macro_export)]
#[cfg(not(feature = "nightly"))]
macro_rules! json_str {
	($j:tt) => ({
		let json_raw = stringify!($j);
		let mut json = String::with_capacity(json_raw.len());
		$crate::parse::sanitise(json_raw.as_bytes(), &mut json);

		json
	})
}
<|endoftext|>


<commit_before>#![crate_name = "neovim"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![allow(raw_pointer_deriving)]

extern crate libc;

use std::c_str::CString;
use std::string::String;
use std::vec::Vec;

#[cfg(target_os="macos")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "curses")]
    #[link(name = "iconv")]
    extern{}
}

#[cfg(target_os="linux")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "curses")]
    extern{}
}

#[cfg(target_os="windows")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "curses")]
    extern{}
}

mod ffi {
    pub use libc::{c_char, c_double, c_int, int64_t, uint64_t};
    pub use libc::types::os::arch::c95::size_t;

    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_msgpack_sbuffer {
        pub size: size_t,
        pub data: *const c_char,
        pub alloc: size_t,
    }
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_Object;
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_KeyValuePair;
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_String {
        pub data: *const c_char,
        pub size: size_t,
    }
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_Array {
        pub items: *mut C_Object,
        pub size: size_t,
        pub capacity: size_t,
    }
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_Dictionary {
        pub items: *mut C_KeyValuePair,
        pub size: size_t,
        pub capacity: size_t,
    }

    pub type Buffer = uint64_t;
    pub type Window = uint64_t;
    pub type Tabpage = uint64_t;
    pub type Integer = int64_t;
    pub type Boolean = bool;
    pub type Float = c_double;

    extern "C" {
        pub fn nvim_main (argc: c_int, argv: *const *const c_char,
                          read_fd: c_int, write_fd: c_int) -> c_int;
        pub fn vim_array_new () -> *mut C_Array;
        pub fn vim_array_free (arr: *mut C_Array);
        pub fn vim_array_add_buffer (val: Buffer, arr: *mut C_Array);
        pub fn vim_array_add_window (val: Window, arr: *mut C_Array);
        pub fn vim_array_add_tabpage (val: Tabpage, arr: *mut C_Array);
        pub fn vim_array_add_nil (arr: *mut C_Array);
        pub fn vim_array_add_boolean (val: Boolean, arr: *mut C_Array);
        pub fn vim_array_add_integer (val: Integer, arr: *mut C_Array);
        pub fn vim_array_add_float (val: Float, arr: *mut C_Array);
        pub fn vim_array_add_string (val: C_String, arr: *mut C_Array);
        pub fn vim_array_add_array (val: C_Array, arr: *mut C_Array);
        pub fn vim_array_add_dictionary (val: C_Dictionary, arr: *mut C_Array);
        pub fn vim_msgpack_new () -> *mut C_msgpack_sbuffer;
        pub fn vim_msgpack_free (buf: *mut C_msgpack_sbuffer);
        pub fn vim_serialize_request (request_id: uint64_t, method: C_String, args: C_Array, buf: *mut C_msgpack_sbuffer);
    }
}

#[deriving(Copy)]
pub struct Array {
    pointer: *mut ffi::C_Array
}

impl Array {
    pub fn new() -> Array {
        Array {
            pointer: ::std::ptr::null_mut()
        }
    }

    pub fn add_buffer(&mut self, val: ffi::Buffer) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_buffer(val, self.pointer) }
    }

    pub fn add_window(&mut self, val: ffi::Window) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_window(val, self.pointer) }
    }

    pub fn add_tabpage(&mut self, val: ffi::Tabpage) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_tabpage(val, self.pointer) }
    }

    pub fn add_nil(&mut self) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_nil(self.pointer) }
    }

    pub fn add_boolean(&mut self, val: ffi::Boolean) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_boolean(val, self.pointer) }
    }

    pub fn add_integer(&mut self, val: ffi::Integer) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_integer(val, self.pointer) }
    }

    pub fn add_float(&mut self, val: ffi::Float) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_float(val, self.pointer) }
    }

    pub fn add_string(&mut self, val: &str) {
        self.check_pointer();
        unsafe {
            ffi::vim_array_add_string(ffi::C_String {data: val.to_c_str().as_ptr(), size: val.len() as u64}, self.pointer)
        }
    }

    pub fn add_array(&mut self, val: Array) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_array(*val.get_pointer(), self.pointer) }
    }

    pub fn add_dictionary(&mut self, val: ffi::C_Dictionary) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_dictionary(val, self.pointer) }
    }

    pub fn serialize_request(&mut self, id: u64, method: &'static str) -> String {
        unsafe {
            let buf = ffi::vim_msgpack_new();
            ffi::vim_serialize_request(id, ffi::C_String {data: method.to_c_str().as_ptr(), size: method.len() as u64}, *self.pointer, buf);
            let s = String::from_raw_buf_len((*buf).data as *const u8, (*buf).size as uint);
            ffi::vim_msgpack_free(buf);
            ffi::vim_array_free(self.pointer);
            self.pointer = ::std::ptr::null_mut();
            s
        }
    }

    #[doc(hidden)]
    pub fn get_pointer(&self) -> *mut ffi::C_Array {
        self.pointer
    }

    #[doc(hidden)]
    pub fn wrap_pointer(c_array: *mut ffi::C_Array) -> Array {
        Array {
            pointer: c_array
        }
    }

    fn check_pointer(&mut self) {
        if self.pointer.is_null() {
            self.pointer = unsafe { ffi::vim_array_new() };
        }
    }
}

impl Drop for Array {
    fn drop(&mut self) {
        if !self.pointer.is_null() {
            unsafe { ffi::vim_array_free(self.pointer) };
        }
        self.pointer = ::std::ptr::null_mut();
    }
}

#[test]
fn test_request() {
    let mut a = Array::new();
    a.add_integer(80);
    a.add_integer(24);
    println!("{}", a.serialize_request(1, "attach_ui"));
}

pub fn run_with_fds(args: Vec<String>, read_fd: i32, write_fd: i32) -> i32 {
    let v: Vec<CString> = args.iter().map(|s| s.as_slice().to_c_str()).collect();
    let vp: Vec<*const ffi::c_char> = v.iter().map(|s| s.as_ptr()).collect();
    let p_vp: *const *const ffi::c_char = vp.as_ptr();

    unsafe { ffi::nvim_main(vp.len() as i32, p_vp, read_fd, write_fd) }
}

pub fn run(args: Vec<String>) -> i32 {
    run_with_fds(args, -1, -1)
}
<commit_msg>Add clear function<commit_after>#![crate_name = "neovim"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![allow(raw_pointer_deriving)]

extern crate libc;

use std::c_str::CString;
use std::string::String;
use std::vec::Vec;

#[cfg(target_os="macos")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "curses")]
    #[link(name = "iconv")]
    extern{}
}

#[cfg(target_os="linux")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "curses")]
    extern{}
}

#[cfg(target_os="windows")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "curses")]
    extern{}
}

mod ffi {
    pub use libc::{c_char, c_double, c_int, int64_t, uint64_t};
    pub use libc::types::os::arch::c95::size_t;

    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_msgpack_sbuffer {
        pub size: size_t,
        pub data: *const c_char,
        pub alloc: size_t,
    }
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_Object;
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_KeyValuePair;
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_String {
        pub data: *const c_char,
        pub size: size_t,
    }
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_Array {
        pub items: *mut C_Object,
        pub size: size_t,
        pub capacity: size_t,
    }
    #[repr(C)]
    #[deriving(Copy)]
    pub struct C_Dictionary {
        pub items: *mut C_KeyValuePair,
        pub size: size_t,
        pub capacity: size_t,
    }

    pub type Buffer = uint64_t;
    pub type Window = uint64_t;
    pub type Tabpage = uint64_t;
    pub type Integer = int64_t;
    pub type Boolean = bool;
    pub type Float = c_double;

    extern "C" {
        pub fn nvim_main (argc: c_int, argv: *const *const c_char,
                          read_fd: c_int, write_fd: c_int) -> c_int;
        pub fn vim_array_new () -> *mut C_Array;
        pub fn vim_array_free (arr: *mut C_Array);
        pub fn vim_array_add_buffer (val: Buffer, arr: *mut C_Array);
        pub fn vim_array_add_window (val: Window, arr: *mut C_Array);
        pub fn vim_array_add_tabpage (val: Tabpage, arr: *mut C_Array);
        pub fn vim_array_add_nil (arr: *mut C_Array);
        pub fn vim_array_add_boolean (val: Boolean, arr: *mut C_Array);
        pub fn vim_array_add_integer (val: Integer, arr: *mut C_Array);
        pub fn vim_array_add_float (val: Float, arr: *mut C_Array);
        pub fn vim_array_add_string (val: C_String, arr: *mut C_Array);
        pub fn vim_array_add_array (val: C_Array, arr: *mut C_Array);
        pub fn vim_array_add_dictionary (val: C_Dictionary, arr: *mut C_Array);
        pub fn vim_msgpack_new () -> *mut C_msgpack_sbuffer;
        pub fn vim_msgpack_free (buf: *mut C_msgpack_sbuffer);
        pub fn vim_serialize_request (request_id: uint64_t, method: C_String, args: C_Array, buf: *mut C_msgpack_sbuffer);
    }
}

#[deriving(Copy)]
pub struct Array {
    pointer: *mut ffi::C_Array
}

impl Array {
    pub fn new() -> Array {
        Array {
            pointer: ::std::ptr::null_mut()
        }
    }

    pub fn add_buffer(&mut self, val: ffi::Buffer) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_buffer(val, self.pointer) }
    }

    pub fn add_window(&mut self, val: ffi::Window) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_window(val, self.pointer) }
    }

    pub fn add_tabpage(&mut self, val: ffi::Tabpage) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_tabpage(val, self.pointer) }
    }

    pub fn add_nil(&mut self) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_nil(self.pointer) }
    }

    pub fn add_boolean(&mut self, val: ffi::Boolean) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_boolean(val, self.pointer) }
    }

    pub fn add_integer(&mut self, val: ffi::Integer) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_integer(val, self.pointer) }
    }

    pub fn add_float(&mut self, val: ffi::Float) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_float(val, self.pointer) }
    }

    pub fn add_string(&mut self, val: &str) {
        self.check_pointer();
        unsafe {
            ffi::vim_array_add_string(ffi::C_String {data: val.to_c_str().as_ptr(), size: val.len() as u64}, self.pointer)
        }
    }

    pub fn add_array(&mut self, val: Array) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_array(*val.get_pointer(), self.pointer) }
    }

    pub fn add_dictionary(&mut self, val: ffi::C_Dictionary) {
        self.check_pointer();
        unsafe { ffi::vim_array_add_dictionary(val, self.pointer) }
    }

    pub fn serialize_request(&mut self, id: u64, method: &'static str) -> String {
        unsafe {
            let buf = ffi::vim_msgpack_new();
            ffi::vim_serialize_request(id, ffi::C_String {data: method.to_c_str().as_ptr(), size: method.len() as u64}, *self.pointer, buf);
            let s = String::from_raw_buf_len((*buf).data as *const u8, (*buf).size as uint);
            ffi::vim_msgpack_free(buf);
            s
        }
    }

    pub fn clear(&mut self) {
        if !self.pointer.is_null() {
            unsafe { ffi::vim_array_free(self.pointer) };
        }
        self.pointer = ::std::ptr::null_mut();
    }

    #[doc(hidden)]
    pub fn get_pointer(&self) -> *mut ffi::C_Array {
        self.pointer
    }

    #[doc(hidden)]
    pub fn wrap_pointer(c_array: *mut ffi::C_Array) -> Array {
        Array {
            pointer: c_array
        }
    }

    fn check_pointer(&mut self) {
        if self.pointer.is_null() {
            self.pointer = unsafe { ffi::vim_array_new() };
        }
    }
}

impl Drop for Array {
    fn drop(&mut self) {
        self.clear();
    }
}

#[test]
fn test_request() {
    let mut a = Array::new();
    a.add_integer(80);
    a.add_integer(24);
    println!("{}", a.serialize_request(1, "attach_ui"));
}

pub fn run_with_fds(args: Vec<String>, read_fd: i32, write_fd: i32) -> i32 {
    let v: Vec<CString> = args.iter().map(|s| s.as_slice().to_c_str()).collect();
    let vp: Vec<*const ffi::c_char> = v.iter().map(|s| s.as_ptr()).collect();
    let p_vp: *const *const ffi::c_char = vp.as_ptr();

    unsafe { ffi::nvim_main(vp.len() as i32, p_vp, read_fd, write_fd) }
}

pub fn run(args: Vec<String>) -> i32 {
    run_with_fds(args, -1, -1)
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(collections)]
#![feature(core)]
#![feature(exit_status)]
#![feature(old_io)]
#![feature(path)]
#![feature(rustc_private)]
#![feature(std_misc)]
#![feature(test)]

extern crate getopts;
extern crate test;

use test::{AutoColor, TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use test::ShouldPanic;
use getopts::{getopts, reqopt};
use std::{str, env};
use std::ffi::OsStr;
use std::fs::read_dir;
use std::old_io::Reader;
use std::old_io::process::{Command, Ignored, CreatePipe, InheritFd, ExitStatus};
use std::thunk::Thunk;

#[derive(Clone)]
struct Config {
    source_dir: String,
    filter: Option<String>
}

fn main() {
    let args = env::args();
    let config = parse_config(args.collect());
    let opts = test_options(config.clone());
    let tests = find_tests(config);
    match run_tests_console(&opts, tests) {
        Ok(false) => env::set_exit_status(1), // tests failed
        Err(_) => env::set_exit_status(2),    // I/O-related failure
        _ => (),
    }
}

fn parse_config(args: Vec<String>) -> Config {
    let args = args.tail();
    let opts = vec!(reqopt("s", "source-dir", "source-dir", "source-dir"));
    let matches = match getopts(args, opts.as_slice()) {
      Ok(m) => m,
      Err(f) => panic!(f.to_string())
    };

    Config {
        source_dir: matches.opt_str("source-dir").unwrap(),
        filter: matches.free.first().map(|s| s.clone())
    }
}

fn test_options(config: Config) -> TestOpts {
    TestOpts {
        filter: config.filter,
        run_ignored: false,
        run_tests: true,
        run_benchmarks: false,
        logfile: None,
        nocapture: false,
        color: AutoColor,
    }
}

fn find_tests(config: Config) -> Vec<TestDescAndFn> {
    read_dir(&config.source_dir)
        .ok()
        .expect("Error reading directory.")
        .filter_map(Result::ok)
        .map(|e| e.path())
        .filter(|file| file.extension().map_or(false, |e| e == OsStr::from_str("html")))
        .map(|file| make_test(file.display().to_string()))
        .collect()
}

fn make_test(file: String) -> TestDescAndFn {
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(file.clone()),
            ignore: false,
            should_panic: ShouldPanic::No,
        },
        testfn: DynTestFn(Thunk::new(move || { run_test(file) }))
    }
}

fn run_test(file: String) {
    let path = env::current_dir().unwrap().join(&file);
    // FIXME (#1094): not the right way to transform a path
    let infile = format!("file://{}", path.display());
    let stdout = CreatePipe(false, true);
    let stderr = InheritFd(2);
    let args = ["-z", "-f", infile.as_slice()];

    let mut prc_arg = env::current_exe().unwrap();
    let prc_arg = match prc_arg.pop() {
        true => prc_arg.join("servo"),
        _ => panic!("could not pop directory"),
    };
    let mut prc = match Command::new(prc_arg.to_str().unwrap())
        .args(args.as_slice())
        .stdin(Ignored)
        .stdout(stdout)
        .stderr(stderr)
        .spawn()
    {
        Ok(p) => p,
        _ => panic!("Unable to spawn process."),
    };
    let mut output = Vec::new();
    loop {
        let byte = prc.stdout.as_mut().unwrap().read_byte();
        match byte {
            Ok(byte) => {
                print!("{}", byte as char);
                output.push(byte);
            }
            _ => break
        }
    }

    let out = str::from_utf8(output.as_slice());
    let lines: Vec<&str> = out.unwrap().split('\n').collect();
    for &line in lines.iter() {
        if line.contains("TEST-UNEXPECTED-FAIL") {
            panic!(line.to_string());
        }
    }

    let retval = prc.wait();
    if retval != Ok(ExitStatus(0)) {
        panic!("Servo exited with non-zero status {:?}", retval);
    }
}
<commit_msg>auto merge of #5418 : Ms2ger/servo/contenttest, r=jdm<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(collections)]
#![feature(exit_status)]
#![feature(path)]
#![feature(rustc_private)]
#![feature(std_misc)]
#![feature(test)]

extern crate getopts;
extern crate test;

use test::{AutoColor, TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use test::ShouldPanic;
use getopts::{getopts, reqopt};
use std::{str, env};
use std::ffi::OsStr;
use std::fs::read_dir;
use std::process::{Command, Stdio};
use std::thunk::Thunk;

#[derive(Clone)]
struct Config {
    source_dir: String,
    filter: Option<String>
}

fn main() {
    let args = env::args();
    let config = parse_config(args.collect());
    let opts = test_options(config.clone());
    let tests = find_tests(config);
    match run_tests_console(&opts, tests) {
        Ok(false) => env::set_exit_status(1), // tests failed
        Err(_) => env::set_exit_status(2),    // I/O-related failure
        _ => (),
    }
}

fn parse_config(args: Vec<String>) -> Config {
    let args = args.tail();
    let opts = vec!(reqopt("s", "source-dir", "source-dir", "source-dir"));
    let matches = match getopts(args, &opts) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };

    Config {
        source_dir: matches.opt_str("source-dir").unwrap(),
        filter: matches.free.first().map(|s| s.clone())
    }
}

fn test_options(config: Config) -> TestOpts {
    TestOpts {
        filter: config.filter,
        run_ignored: false,
        run_tests: true,
        run_benchmarks: false,
        logfile: None,
        nocapture: false,
        color: AutoColor,
    }
}

fn find_tests(config: Config) -> Vec<TestDescAndFn> {
    read_dir(&config.source_dir)
        .ok()
        .expect("Error reading directory.")
        .filter_map(Result::ok)
        .map(|e| e.path())
        .filter(|file| file.extension().map_or(false, |e| e == OsStr::from_str("html")))
        .map(|file| make_test(file.display().to_string()))
        .collect()
}

fn make_test(file: String) -> TestDescAndFn {
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(file.clone()),
            ignore: false,
            should_panic: ShouldPanic::No,
        },
        testfn: DynTestFn(Thunk::new(move || { run_test(file) }))
    }
}

fn run_test(file: String) {
    let path = env::current_dir().unwrap().join(&file);
    // FIXME (#1094): not the right way to transform a path
    let infile = format!("file://{}", path.display());
    let args = ["-z", "-f", &*infile];

    let mut prc_arg = env::current_exe().unwrap();
    let prc_arg = match prc_arg.pop() {
        true => prc_arg.join("servo"),
        _ => panic!("could not pop directory"),
    };
    let output = match Command::new(prc_arg.to_str().unwrap())
        .args(&args)
        .stdin(Stdio::null())
        .stderr(Stdio::inherit())
        .output()
    {
        Ok(p) => p,
        _ => panic!("Unable to spawn process."),
    };

    print!("{}", str::from_utf8(&output.stdout).unwrap());

    let out = str::from_utf8(&output.stderr);
    let lines: Vec<&str> = out.unwrap().split('\n').collect();
    for &line in lines.iter() {
        if line.contains("TEST-UNEXPECTED-FAIL") {
            panic!(line.to_string());
        }
    }

    if !output.status.success() {
        panic!("Servo exited with non-zero status {:?}", output.status);
    }
}
<|endoftext|>


<commit_before>extern crate clap;

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

#[test]
fn only_pos_follow() {
    let r = App::new("onlypos")
        .args(&[Arg::from_usage("-f [flag] 'some opt'"),
                Arg::from_usage("[arg] 'some arg'")])
        .get_matches_from_safe(vec!["", "--", "-f"]);
    assert!(r.is_ok());
    let m = r.unwrap();
    assert!(m.is_present("arg"));
    assert!(!m.is_present("f"));
    assert_eq!(m.value_of("arg").unwrap(), "-f");
}

#[test]
fn positional() {
    let m = App::new("positional")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
            ])
        .get_matches_from(vec!["", "-f", "test"]);
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("positional").unwrap(), "test");

    let m = App::new("positional")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
            ])
        .get_matches_from(vec!["", "test", "--flag"]);
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("positional").unwrap(), "test");
}

#[test]
fn lots_o_vals() {
    let r = App::new("opts")
        .arg(
            Arg::from_usage("[opt]... 'some pos'"),
            )
        .get_matches_from_safe(vec!["",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            ]);
    assert!(r.is_ok());
    let m = r.unwrap();
    assert!(m.is_present("opt"));
    assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>().len(), 297); // i.e. more than u8
}

#[test]
fn positional_multiple() {
    let m = App::new("positional_multiple")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
                .multiple(true)
            ])
        .get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test1", "test2", "test3"]);

    let m = App::new("positional_multiple")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
                .multiple(true)
            ])
        .get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]);
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test1", "test2", "test3"]);
}

#[test]
fn positional_multiple_2() {
    let result = App::new("positional_multiple")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
            ])
        .get_matches_from_safe(vec!["", "-f", "test1", "test2", "test3"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::UnknownArgument);
}

#[test]
fn positional_possible_values() {
    let m = App::new("positional_possible_values")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
                .possible_value("test123")
            ])
        .get_matches_from(vec!["", "-f", "test123"]);
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test123"]);
}

#[test]
fn create_positional() {
    let _ = App::new("test")
                .arg(Arg::with_name("test")
                            .index(1)
                            .help("testing testing"))
                .get_matches_from(vec![""]);
}

#[test]
fn positional_hyphen_does_not_panic() {
    let _ = App::new("test")
        .arg(Arg::with_name("dummy"))
        .get_matches_from(vec!["test", "-"]);
}

#[test]
fn single_positional_usage_string() {
    let m = App::new("test").arg_from_usage("[FILE] 'some file'").get_matches_from(vec!["test"]);
    assert_eq!(m.usage(), "USAGE:\n    test [FILE]");
}

#[test]
fn single_positional_multiple_usage_string() {
    let m = App::new("test").arg_from_usage("[FILE]... 'some file'").get_matches_from(vec!["test"]);
    assert_eq!(m.usage(), "USAGE:\n    test [FILE]...");
}

#[test]
fn multiple_positional_usage_string() {
    let m = App::new("test")
        .arg_from_usage("[FILE] 'some file'")
        .arg_from_usage("[FILES]... 'some file'")
        .get_matches_from(vec!["test"]);
    assert_eq!(m.usage(), "USAGE:\n    test [ARGS]");
}

#[test]
fn multiple_positional_one_required_usage_string() {
    let m = App::new("test")
        .arg_from_usage("<FILE> 'some file'")
        .arg_from_usage("[FILES]... 'some file'")
        .get_matches_from(vec!["test", "file"]);
    assert_eq!(m.usage(), "USAGE:\n    test <FILE> [FILES]...");
}

#[test]
fn single_positional_required_usage_string() {
    let m = App::new("test")
        .arg_from_usage("<FILE> 'some file'")
        .get_matches_from(vec!["test", "file"]);
    assert_eq!(m.usage(), "USAGE:\n    test <FILE>");
}

#[test]
#[should_panic]
fn missing_required() {
    let r = App::new("test")
        .arg_from_usage("[FILE1] 'some file'")
        .arg_from_usage("<FILE2> 'some file'")
        .get_matches_from_safe(vec!["test", "file"]);
    assert!(r.is_err());
    assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}

#[test]
fn missing_required_2() {
    let r = App::new("test")
        .arg_from_usage("<FILE1> 'some file'")
        .arg_from_usage("<FILE2> 'some file'")
        .get_matches_from_safe(vec!["test", "file"]);
    assert!(r.is_err());
    assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}

#[test]
fn last_positional() {
    let r = App::new("test")
        .arg_from_usage("<TARGET> 'some target'")
        .arg_from_usage("[CORPUS] 'some corpus'")
        .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
        .get_matches_from_safe(vec!["test", "tgt", "--", "arg"]);
    assert!(r.is_ok());
    let m = r.unwrap();
    assert_eq!(m.values_of("ARGS").unwrap().collect::<Vec<_>>(), &["arg"]);
}

#[test]
fn last_positional_no_double_dash() {
    let r = App::new("test")
        .arg_from_usage("<TARGET> 'some target'")
        .arg_from_usage("[CORPUS] 'some corpus'")
        .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
        .get_matches_from_safe(vec!["test", "tgt", "crp", "arg"]);
    assert!(r.is_err());
    assert_eq!(r.unwrap_err().kind, ErrorKind::UnknownArgument);
}

#[test]
fn last_positional_second_to_last_mult() {
    let r = App::new("test")
        .arg_from_usage("<TARGET> 'some target'")
        .arg_from_usage("[CORPUS]... 'some corpus'")
        .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
        .get_matches_from_safe(vec!["test", "tgt", "crp1", "crp2", "--", "arg"]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
}<commit_msg>tests: adds tests to ensure flags not incorrectly parsed as positionals<commit_after>extern crate clap;

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

#[test]
fn only_pos_follow() {
    let r = App::new("onlypos")
        .args(&[Arg::from_usage("-f [flag] 'some opt'"),
                Arg::from_usage("[arg] 'some arg'")])
        .get_matches_from_safe(vec!["", "--", "-f"]);
    assert!(r.is_ok());
    let m = r.unwrap();
    assert!(m.is_present("arg"));
    assert!(!m.is_present("f"));
    assert_eq!(m.value_of("arg").unwrap(), "-f");
}

#[test]
fn issue_946() {
    let r = App::new("compiletest")
        .setting(clap::AppSettings::AllowLeadingHyphen)
        .args_from_usage("--exact    'filters match exactly'")
        .arg(clap::Arg::with_name("filter")
            .index(1)
            .takes_value(true)
            .help("filters to apply to output"))
    .get_matches_from_safe(vec!["compiletest", "--exact"]);
    assert!(r.is_ok(), "{:#?}", r);
    let matches = r.unwrap();

    assert!(matches.is_present("exact"));
    assert!(matches.value_of("filter").is_none());
}

#[test]
fn positional() {
    let r = App::new("positional")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
            ])
        .get_matches_from_safe(vec!["", "-f", "test"]);
    assert!(r.is_ok(), "{:#?}", r);
    let m = r.unwrap();
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("positional").unwrap(), "test");

    let m = App::new("positional")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
            ])
        .get_matches_from(vec!["", "test", "--flag"]);
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(m.value_of("positional").unwrap(), "test");
}

#[test]
fn lots_o_vals() {
    let r = App::new("opts")
        .arg(
            Arg::from_usage("[opt]... 'some pos'"),
            )
        .get_matches_from_safe(vec!["",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
            ]);
    assert!(r.is_ok());
    let m = r.unwrap();
    assert!(m.is_present("opt"));
    assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>().len(), 297); // i.e. more than u8
}

#[test]
fn positional_multiple() {
    let r = App::new("positional_multiple")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
                .multiple(true)
            ])
        .get_matches_from_safe(vec!["", "-f", "test1", "test2", "test3"]);
    assert!(r.is_ok(), "{:#?}", r);
    let m = r.unwrap();
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test1", "test2", "test3"]);
}

#[test]
fn positional_multiple_3() {
    let r = App::new("positional_multiple")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
                .multiple(true)
            ])
        .get_matches_from_safe(vec!["", "test1", "test2", "test3", "--flag"]);
    assert!(r.is_ok(), "{:#?}", r);
    let m = r.unwrap();
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test1", "test2", "test3"]);
}

#[test]
fn positional_multiple_2() {
    let result = App::new("positional_multiple")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
            ])
        .get_matches_from_safe(vec!["", "-f", "test1", "test2", "test3"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::UnknownArgument);
}

#[test]
fn positional_possible_values() {
    let r = App::new("positional_possible_values")
        .args(&[
            Arg::from_usage("-f, --flag 'some flag'"),
            Arg::with_name("positional")
                .index(1)
                .possible_value("test123")
            ])
        .get_matches_from_safe(vec!["", "-f", "test123"]);
    assert!(r.is_ok(), "{:#?}", r);
    let m = r.unwrap();
    assert!(m.is_present("positional"));
    assert!(m.is_present("flag"));
    assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test123"]);
}

#[test]
fn create_positional() {
    let _ = App::new("test")
                .arg(Arg::with_name("test")
                            .index(1)
                            .help("testing testing"))
                .get_matches_from(vec![""]);
}

#[test]
fn positional_hyphen_does_not_panic() {
    let _ = App::new("test")
        .arg(Arg::with_name("dummy"))
        .get_matches_from(vec!["test", "-"]);
}

#[test]
fn single_positional_usage_string() {
    let m = App::new("test").arg_from_usage("[FILE] 'some file'").get_matches_from(vec!["test"]);
    assert_eq!(m.usage(), "USAGE:\n    test [FILE]");
}

#[test]
fn single_positional_multiple_usage_string() {
    let m = App::new("test").arg_from_usage("[FILE]... 'some file'").get_matches_from(vec!["test"]);
    assert_eq!(m.usage(), "USAGE:\n    test [FILE]...");
}

#[test]
fn multiple_positional_usage_string() {
    let m = App::new("test")
        .arg_from_usage("[FILE] 'some file'")
        .arg_from_usage("[FILES]... 'some file'")
        .get_matches_from(vec!["test"]);
    assert_eq!(m.usage(), "USAGE:\n    test [ARGS]");
}

#[test]
fn multiple_positional_one_required_usage_string() {
    let m = App::new("test")
        .arg_from_usage("<FILE> 'some file'")
        .arg_from_usage("[FILES]... 'some file'")
        .get_matches_from(vec!["test", "file"]);
    assert_eq!(m.usage(), "USAGE:\n    test <FILE> [FILES]...");
}

#[test]
fn single_positional_required_usage_string() {
    let m = App::new("test")
        .arg_from_usage("<FILE> 'some file'")
        .get_matches_from(vec!["test", "file"]);
    assert_eq!(m.usage(), "USAGE:\n    test <FILE>");
}

#[test]
#[should_panic]
fn missing_required() {
    let r = App::new("test")
        .arg_from_usage("[FILE1] 'some file'")
        .arg_from_usage("<FILE2> 'some file'")
        .get_matches_from_safe(vec!["test", "file"]);
    assert!(r.is_err());
    assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}

#[test]
fn missing_required_2() {
    let r = App::new("test")
        .arg_from_usage("<FILE1> 'some file'")
        .arg_from_usage("<FILE2> 'some file'")
        .get_matches_from_safe(vec!["test", "file"]);
    assert!(r.is_err());
    assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
}

#[test]
fn last_positional() {
    let r = App::new("test")
        .arg_from_usage("<TARGET> 'some target'")
        .arg_from_usage("[CORPUS] 'some corpus'")
        .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
        .get_matches_from_safe(vec!["test", "tgt", "--", "arg"]);
    assert!(r.is_ok());
    let m = r.unwrap();
    assert_eq!(m.values_of("ARGS").unwrap().collect::<Vec<_>>(), &["arg"]);
}

#[test]
fn last_positional_no_double_dash() {
    let r = App::new("test")
        .arg_from_usage("<TARGET> 'some target'")
        .arg_from_usage("[CORPUS] 'some corpus'")
        .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
        .get_matches_from_safe(vec!["test", "tgt", "crp", "arg"]);
    assert!(r.is_err());
    assert_eq!(r.unwrap_err().kind, ErrorKind::UnknownArgument);
}

#[test]
fn last_positional_second_to_last_mult() {
    let r = App::new("test")
        .arg_from_usage("<TARGET> 'some target'")
        .arg_from_usage("[CORPUS]... 'some corpus'")
        .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
        .get_matches_from_safe(vec!["test", "tgt", "crp1", "crp2", "--", "arg"]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
}<|endoftext|>


<commit_before>//! This crate provides abstractions over the `energymon_sys` and `energymon_default_sys` crates
//! using the EnergyMonitor trait.

extern crate libc;
extern crate energy_monitor;
extern crate energymon_default_sys;

use libc::{c_char, size_t};
use std::mem;
use energy_monitor::EnergyMonitor;
use energymon_default_sys::{energymon, energymon_get_default};

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: energymon,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
        unsafe {
            let mut em: energymon = mem::uninitialized();
            match energymon_get_default(&mut em) {
                0 => (),
                _ => return Err("Failed to create energymon"),
            }
            match (em.finit)(&mut em) {
                0 => Ok(EnergyMon{ em: em }),
                _ => Err("Failed to initialize energymon"),
            }
        }
    }

    /// Cleanup the `EnergyMon`.
    fn finish(&mut self) -> i32 {
        (self.em.ffinish)(&mut self.em)
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        self.finish();
    }
}

impl EnergyMonitor for EnergyMon {
    fn read_uj(&self) -> Result<u64, &'static str> {
        Ok((self.em.fread)(&self.em))
    }

    fn source(&self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.em.fsource)(buf.as_mut_ptr(),
                                                 mem::size_of_val(&buf) as size_t);
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    fn interval_us(&self) -> u64 {
        (self.em.finterval)(&self.em)
    }
}

#[cfg(test)]
mod test {
    use super::EnergyMon;
    use energy_monitor::EnergyMonitor;

    #[test]
    fn test_interface() {
        let em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read_uj().unwrap();
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval_us());
    }

}
<commit_msg>Safer conversion from c_char array to String. Fixes #1.<commit_after>//! This crate provides abstractions over the `energymon_sys` and `energymon_default_sys` crates
//! using the EnergyMonitor trait.

extern crate libc;
extern crate energy_monitor;
extern crate energymon_default_sys;

use libc::{c_char, size_t};
use std::ffi::CStr;
use std::mem;
use energy_monitor::EnergyMonitor;
use energymon_default_sys::{energymon, energymon_get_default};

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: energymon,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
        unsafe {
            let mut em: energymon = mem::uninitialized();
            match energymon_get_default(&mut em) {
                0 => (),
                _ => return Err("Failed to create energymon"),
            }
            match (em.finit)(&mut em) {
                0 => Ok(EnergyMon{ em: em }),
                _ => Err("Failed to initialize energymon"),
            }
        }
    }

    /// Cleanup the `EnergyMon`.
    fn finish(&mut self) -> i32 {
        (self.em.ffinish)(&mut self.em)
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        self.finish();
    }
}

impl EnergyMonitor for EnergyMon {
    fn read_uj(&self) -> Result<u64, &'static str> {
        Ok((self.em.fread)(&self.em))
    }

    fn source(&self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.em.fsource)(buf.as_mut_ptr(),
                                                 mem::size_of_val(&buf) as size_t);
        match ret.is_null() {
            true => "UNKNOWN".to_owned(),
            false => unsafe {
                String::from_utf8_lossy(CStr::from_ptr(buf.as_mut_ptr()).to_bytes()).into_owned()
            }
        }
    }

    fn interval_us(&self) -> u64 {
        (self.em.finterval)(&self.em)
    }
}

#[cfg(test)]
mod test {
    use super::EnergyMon;
    use energy_monitor::EnergyMonitor;

    #[test]
    fn test_interface() {
        let em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read_uj().unwrap();
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval_us());
    }

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Rurel is a flexible, reusable reinforcement learning (Q learning) implementation in Rust.
//!
//! Implement the [Agent](mdp/trait.Agent.html) and [State](mdp/trait.State.html) traits for your
//! process, then create an [AgentTrainer](struct.AgentTrainer.html) and train it for your process.
//!
//! # Basic Example
//!
//! The following example defines the `State` as a position on a 21x21 2D matrix. The `Action`s
//! that can be taken are: go up, go down, go left and go right. Positions closer to (10, 10) are
//! assigned a higher reward.
//!
//! After training, the AgentTrainer will have assigned higher values to actions which move closer
//! to (10, 10).
//!
//! ```
//! use rurel::mdp::{State, Agent};
//!
//! #[derive(PartialEq, Eq, Hash, Clone)]
//! struct MyState { x: i32, y: i32 }
//! #[derive(PartialEq, Eq, Hash, Clone)]
//! struct MyAction { dx: i32, dy: i32 }
//!
//! impl State for MyState {
//!     type A = MyAction;
//!     fn reward(&self) -> f64 {
//!         // Negative Euclidean distance
//!         -((((10 - self.x).pow(2) + (10 - self.y).pow(2)) as f64).sqrt())
//!     }
//!     fn actions(&self) -> Vec<MyAction> {
//!         vec![MyAction { dx: 0, dy: -1 },    // up
//!              MyAction { dx: 0, dy: 1 }, // down
//!              MyAction { dx: -1, dy: 0 },    // left
//!              MyAction { dx: 1, dy: 0 }, // right
//!         ]
//!     }
//! }
//!
//! struct MyAgent { state: MyState }
//! impl Agent<MyState> for MyAgent {
//!     fn current_state(&self) -> &MyState {
//!         &self.state
//!     }
//!     fn take_action(&mut self, action: &MyAction) -> () {
//!         match action {
//!             &MyAction { dx, dy } => {
//!                 self.state = MyState {
//!                     x: (((self.state.x + dx) % 21) + 21) % 21, // (x+dx) mod 21
//!                     y: (((self.state.y + dy) % 21) + 21) % 21, // (y+dy) mod 21
//!                 }
//!             }
//!         }
//!     }
//! }
//!
//! use rurel::AgentTrainer;
//! use rurel::strategy::learn::QLearning;
//! use rurel::strategy::explore::RandomExploration;
//! use rurel::strategy::terminate::FixedIterations;
//!
//! let mut trainer = AgentTrainer::new();
//! let mut agent = MyAgent { state: MyState { x: 0, y: 0 }};
//! trainer.train(&mut agent,
//!               &QLearning::new(0.2, 0.01, 2.),
//!               &mut FixedIterations::new(100000),
//!               &RandomExploration::new());
//!
//! // Test to see if it worked
//! let test_state = MyState { x: 10, y: 9 };
//! let go_up = MyAction { dx: 0, dy: -1 };
//! let go_down = MyAction { dx: 0, dy: 1};
//! // Going down is better than going up
//! assert!(trainer.expected_value(&test_state, &go_down)
//!     > trainer.expected_value(&test_state, &go_up));
//! ```

pub mod mdp;
pub mod strategy;

use mdp::{Agent, State};
use std::collections::HashMap;
use strategy::explore::ExplorationStrategy;
use strategy::learn::LearningStrategy;
use strategy::terminate::TerminationStrategy;

/// An `AgentTrainer` can be trained for using a certain [Agent](mdp/trait.Agent.html). After
/// training, the `AgentTrainer` contains learned knowledge about the process, and can be queried
/// for this. For example, you can ask the `AgentTrainer` the expected values of all possible
/// actions in a given state.
pub struct AgentTrainer<S>
where
    S: State,
{
    q: HashMap<S, HashMap<S::A, f64>>,
}

impl<S> AgentTrainer<S>
where
    S: State,
{
    pub fn new() -> AgentTrainer<S> {
        AgentTrainer { q: HashMap::new() }
    }
    /// Fetches the learned values for the given state, by `Action`, or `None` if no value was
    /// learned.
    pub fn expected_values(&self, state: &S) -> Option<&HashMap<S::A, f64>> {
        // XXX: make associated const with empty map and remove Option?
        self.q.get(state)
    }
    /// Fetches the learned value for the given `Action` in the given `State`, or `None` if no
    /// value was learned.
    pub fn expected_value(&self, state: &S, action: &S::A) -> Option<f64> {
        self.q.get(state).and_then(|m| m.get(action).copied())
    }
    /// Returns a clone of the entire learned state to be saved or used elsewhere.
    pub fn export_learned_values(&self) -> HashMap<S, HashMap<S::A, f64>> {
        self.q.clone()
    }
    /// Imports a state, completely replacing any learned progress
    pub fn import_state(&mut self, q: HashMap<S, HashMap<S::A, f64>>) {
        self.q = q;
    }
    /// Trains this [AgentTrainer] using the given [ExplorationStrategy], [LearningStrategy] and
    /// [Agent] until the [TerminationStrategy] decides to stop.
    pub fn train(
        &mut self,
        agent: &mut dyn Agent<S>,
        learning_strategy: &dyn LearningStrategy<S>,
        termination_strategy: &mut dyn TerminationStrategy<S>,
        exploration_strategy: &dyn ExplorationStrategy<S>,
    ) {
        loop {
            let s_t = agent.current_state().clone();
            let action = exploration_strategy.pick_action(agent);

            // current action value
            let s_t_next = agent.current_state();
            let r_t_next = s_t_next.reward();

            let v = {
                let old_value = self.q.get(&s_t).and_then(|m| m.get(&action));
                learning_strategy.value(&self.q.get(s_t_next), &old_value, r_t_next)
            };

            self.q
                .entry(s_t)
                .or_insert_with(HashMap::new)
                .insert(action, v);

            if termination_strategy.should_stop(&s_t_next) {
                break;
            }
        }
    }
}

impl<S: mdp::State> Default for AgentTrainer<S> {
    fn default() -> Self {
        Self::new()
    }
}
<commit_msg>Added possibility to retrieve best action for a state<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Rurel is a flexible, reusable reinforcement learning (Q learning) implementation in Rust.
//!
//! Implement the [Agent](mdp/trait.Agent.html) and [State](mdp/trait.State.html) traits for your
//! process, then create an [AgentTrainer](struct.AgentTrainer.html) and train it for your process.
//!
//! # Basic Example
//!
//! The following example defines the `State` as a position on a 21x21 2D matrix. The `Action`s
//! that can be taken are: go up, go down, go left and go right. Positions closer to (10, 10) are
//! assigned a higher reward.
//!
//! After training, the AgentTrainer will have assigned higher values to actions which move closer
//! to (10, 10).
//!
//! ```
//! use rurel::mdp::{State, Agent};
//!
//! #[derive(PartialEq, Eq, Hash, Clone)]
//! struct MyState { x: i32, y: i32 }
//! #[derive(PartialEq, Eq, Hash, Clone)]
//! struct MyAction { dx: i32, dy: i32 }
//!
//! impl State for MyState {
//!     type A = MyAction;
//!     fn reward(&self) -> f64 {
//!         // Negative Euclidean distance
//!         -((((10 - self.x).pow(2) + (10 - self.y).pow(2)) as f64).sqrt())
//!     }
//!     fn actions(&self) -> Vec<MyAction> {
//!         vec![MyAction { dx: 0, dy: -1 },    // up
//!              MyAction { dx: 0, dy: 1 }, // down
//!              MyAction { dx: -1, dy: 0 },    // left
//!              MyAction { dx: 1, dy: 0 }, // right
//!         ]
//!     }
//! }
//!
//! struct MyAgent { state: MyState }
//! impl Agent<MyState> for MyAgent {
//!     fn current_state(&self) -> &MyState {
//!         &self.state
//!     }
//!     fn take_action(&mut self, action: &MyAction) -> () {
//!         match action {
//!             &MyAction { dx, dy } => {
//!                 self.state = MyState {
//!                     x: (((self.state.x + dx) % 21) + 21) % 21, // (x+dx) mod 21
//!                     y: (((self.state.y + dy) % 21) + 21) % 21, // (y+dy) mod 21
//!                 }
//!             }
//!         }
//!     }
//! }
//!
//! use rurel::AgentTrainer;
//! use rurel::strategy::learn::QLearning;
//! use rurel::strategy::explore::RandomExploration;
//! use rurel::strategy::terminate::FixedIterations;
//!
//! let mut trainer = AgentTrainer::new();
//! let mut agent = MyAgent { state: MyState { x: 0, y: 0 }};
//! trainer.train(&mut agent,
//!               &QLearning::new(0.2, 0.01, 2.),
//!               &mut FixedIterations::new(100000),
//!               &RandomExploration::new());
//!
//! // Test to see if it worked
//! let test_state = MyState { x: 10, y: 9 };
//! let go_up = MyAction { dx: 0, dy: -1 };
//! let go_down = MyAction { dx: 0, dy: 1};
//! // Going down is better than going up
//! assert!(trainer.expected_value(&test_state, &go_down)
//!     > trainer.expected_value(&test_state, &go_up));
//! ```

pub mod mdp;
pub mod strategy;

use mdp::{Agent, State};
use std::collections::HashMap;
use strategy::explore::ExplorationStrategy;
use strategy::learn::LearningStrategy;
use strategy::terminate::TerminationStrategy;

/// An `AgentTrainer` can be trained for using a certain [Agent](mdp/trait.Agent.html). After
/// training, the `AgentTrainer` contains learned knowledge about the process, and can be queried
/// for this. For example, you can ask the `AgentTrainer` the expected values of all possible
/// actions in a given state.
pub struct AgentTrainer<S>
where
    S: State,
{
    q: HashMap<S, HashMap<S::A, f64>>,
}

impl<S> AgentTrainer<S>
where
    S: State,
{
    pub fn new() -> AgentTrainer<S> {
        AgentTrainer { q: HashMap::new() }
    }
    /// Fetches the learned values for the given state, by `Action`, or `None` if no value was
    /// learned.
    pub fn expected_values(&self, state: &S) -> Option<&HashMap<S::A, f64>> {
        // XXX: make associated const with empty map and remove Option?
        self.q.get(state)
    }
    /// Fetches the learned value for the given `Action` in the given `State`, or `None` if no
    /// value was learned.
    pub fn expected_value(&self, state: &S, action: &S::A) -> Option<f64> {
        self.q.get(state).and_then(|m| m.get(action).copied())
    }
    /// Returns a clone of the entire learned state to be saved or used elsewhere.
    pub fn export_learned_values(&self) -> HashMap<S, HashMap<S::A, f64>> {
        self.q.clone()
    }
    /// Imports a state, completely replacing any learned progress
    pub fn import_state(&mut self, q: HashMap<S, HashMap<S::A, f64>>) {
        self.q = q;
    }
    /// Returns the best action for the given `State`, or `None` if no values were learned.
    pub fn best_action(&self, state: &S) -> Option<S::A> {
        self.expected_values(state)
            .and_then(|m| m.iter().max_by(|&(_,v1),&(_,v2)| v1.partial_cmp(v2).unwrap()))
            .map(|t| t.0.clone())
    }
    /// Trains this [AgentTrainer] using the given [ExplorationStrategy], [LearningStrategy] and
    /// [Agent] until the [TerminationStrategy] decides to stop.
    pub fn train(
        &mut self,
        agent: &mut dyn Agent<S>,
        learning_strategy: &dyn LearningStrategy<S>,
        termination_strategy: &mut dyn TerminationStrategy<S>,
        exploration_strategy: &dyn ExplorationStrategy<S>,
    ) {
        loop {
            let s_t = agent.current_state().clone();
            let action = exploration_strategy.pick_action(agent);

            // current action value
            let s_t_next = agent.current_state();
            let r_t_next = s_t_next.reward();

            let v = {
                let old_value = self.q.get(&s_t).and_then(|m| m.get(&action));
                learning_strategy.value(&self.q.get(s_t_next), &old_value, r_t_next)
            };

            self.q
                .entry(s_t)
                .or_insert_with(HashMap::new)
                .insert(action, v);

            if termination_strategy.should_stop(&s_t_next) {
                break;
            }
        }
    }
}

impl<S: mdp::State> Default for AgentTrainer<S> {
    fn default() -> Self {
        Self::new()
    }
}
<|endoftext|>


<commit_before>// DOCS

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, p.parent().unwrap_or(p))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<E, F: FnMut(&mut fs::File) -> io::Result<E>>(&self, mut f: F) -> io::Result<E> {
        let tmpdir = try!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = try!({
            let mut tmpfile = try!(fs::File::create(&tmppath));
            f(&mut tmpfile)
        });
        try!(self.commit(&tmppath));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    extern crate nix;

    use std::{io,fs,path};
    use std::os::unix::io::AsRawFd;

    fn fsync_dir(x: &path::Path) -> io::Result<()> {
        let f = try!(fs::File::open(x));
        try!(nix::unistd::fsync(f.as_raw_fd()));
        Ok(())
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::rename(src, dst));

        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        Ok(())
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        try!(fs::remove_file(src));

        let src_directory = src.parent().unwrap();
        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        if src_directory != dst_directory { try!(fsync_dir(src_directory)); }
        Ok(())
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32 as win32kernel;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH | winapi::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<commit_msg>Generalize the type of `AtomicFile::write`<commit_after>// DOCS

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, p.parent().unwrap_or(p))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<T, E, F>(&self, f: F) -> Result<T, E> where
        E: From<io::Error>,
        F: FnOnce(&mut fs::File) -> Result<T, E>
    {
        let tmpdir = try!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = try!({
            let mut tmpfile = try!(fs::File::create(&tmppath));
            f(&mut tmpfile)
        });
        try!(self.commit(&tmppath));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    extern crate nix;

    use std::{io,fs,path};
    use std::os::unix::io::AsRawFd;

    fn fsync_dir(x: &path::Path) -> io::Result<()> {
        let f = try!(fs::File::open(x));
        try!(nix::unistd::fsync(f.as_raw_fd()));
        Ok(())
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::rename(src, dst));

        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        Ok(())
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        try!(fs::remove_file(src));

        let src_directory = src.parent().unwrap();
        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        if src_directory != dst_directory { try!(fsync_dir(src_directory)); }
        Ok(())
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32 as win32kernel;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH | winapi::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<|endoftext|>


<commit_before>
use std::fs::File;
use std::io::{self, BufRead};
use regex::Regex;

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge {
    count: usize,
    states: Vec<State<u32>>
}

impl Merge {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let mut states: Vec<State<u32>> = Vec::with_capacity(count);
        for i in 0..count {
            let collection = Box::new(get_collection(filename, i).unwrap());
            let state = State(collection, None);
            states.push(state);
        }
        Merge{count: count, states: states}
    }
}

impl Iterator for Merge  {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let mut state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let not_done = states.iter().any(|s| s.1.is_some());
            if !not_done {
                return None;
            }

            let mut min = u32::MAX;
            let mut min_index = usize::MIN;
            for i in 0..count {
                let state = &mut states[i];
                if let Some(val) = state.1 {
                    if val < min {
                        min = val;
                        min_index = i;
                    }
                }
            }
            states[min_index].1 = None;
            return Some(min);
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output(filename: &str) -> io::Result<impl Iterator<Item = u32>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = u32>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = u32>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<u32> {
        if let Ok(i) = v.parse::<u32>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches.map(move |s| {
        let numbers = s.split(',').filter_map(|v| to_int(&v));
        numbers.collect::<Vec<_>>()
    }).flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line|
            line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches = lines.filter_map(move |line| {
        r.captures(&line).map(|captures|
            captures[1].to_string()
        )
    });
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap() , 3);
    }

    #[test]
    fn test_output() {
        let output = [1,1,2,2,3,4,4,6,7,9,9,20,21];
        assert_eq!(get_output("../data/test.txt").unwrap().collect::<Vec<_>>(), output);
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(get_collection("../data/test.txt", 1).unwrap().collect::<Vec<_>>(), output);
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator(iter1: &mut impl Iterator<Item = u32>, iter2: &mut impl Iterator<Item = u32>) -> bool {
        loop {
            let v1 = iter1.next();
            let v2 = iter2.next();
            if v1.is_none() && v2.is_none() {
                return true;
            }
            else if v1.is_some() && v2.is_some() {
                if v1.unwrap() == v2.unwrap() {
                    continue;
                }
            }
            return false;
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<commit_msg>Use a match<commit_after>
use std::fs::File;
use std::io::{self, BufRead};
use regex::Regex;

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge {
    count: usize,
    states: Vec<State<u32>>
}

impl Merge {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let mut states: Vec<State<u32>> = Vec::with_capacity(count);
        for i in 0..count {
            let collection = Box::new(get_collection(filename, i).unwrap());
            let state = State(collection, None);
            states.push(state);
        }
        Merge{count: count, states: states}
    }
}

impl Iterator for Merge  {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let mut state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let not_done = states.iter().any(|s| s.1.is_some());
            if !not_done {
                return None;
            }

            let mut min = u32::MAX;
            let mut min_index = usize::MIN;
            for i in 0..count {
                let state = &mut states[i];
                if let Some(val) = state.1 {
                    if val < min {
                        min = val;
                        min_index = i;
                    }
                }
            }
            states[min_index].1 = None;
            return Some(min);
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output(filename: &str) -> io::Result<impl Iterator<Item = u32>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = u32>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = u32>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<u32> {
        if let Ok(i) = v.parse::<u32>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches.map(move |s| {
        let numbers = s.split(',').filter_map(|v| to_int(&v));
        numbers.collect::<Vec<_>>()
    }).flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line|
            line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches = lines.filter_map(move |line| {
        r.captures(&line).map(|captures|
            captures[1].to_string()
        )
    });
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap() , 3);
    }

    #[test]
    fn test_output() {
        let output = [1,1,2,2,3,4,4,6,7,9,9,20,21];
        assert_eq!(get_output("../data/test.txt").unwrap().collect::<Vec<_>>(), output);
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(get_collection("../data/test.txt", 1).unwrap().collect::<Vec<_>>(), output);
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator(iter1: &mut impl Iterator<Item = u32>, iter2: &mut impl Iterator<Item = u32>) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate ai_behavior;
extern crate sprite;
extern crate graphics;
extern crate sdl2_window;
extern crate opengl_graphics;

use std::path::Path;
use std::cell::RefCell;
use std::rc::Rc;

use sprite::*;
use ai_behavior::{
    Action,
    Sequence,
    Wait,
    WaitForever,
    While,
};

use sdl2_window::Sdl2Window;
use opengl_graphics::{
    GlGraphics,
    OpenGL,
    Texture,
};

fn main() {
    let (width, height) = (300, 300);
    let opengl = OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        piston::window::WindowSettings {
            title: "piston-example-sprite".to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut scene = Scene::new();
    let tex = Path::new("./bin/assets/rust-logo.png");
    let tex = Rc::new(Texture::from_path(&tex).unwrap());
    let mut sprite = Sprite::from_texture(tex.clone());
    sprite.set_position(width as f64 / 2.0, height as f64 / 2.0);

    let id = scene.add_child(sprite);

    // Run a sequence or animations.
    let seq = Sequence(vec![
        Action(Ease(EaseFunction::CubicOut, Box::new(ScaleTo(2.0, 0.5, 0.5)))),
        Action(Ease(EaseFunction::BounceOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Ease(EaseFunction::ElasticOut, Box::new(MoveBy(2.0, 0.0, -100.0)))),
        Action(Ease(EaseFunction::BackInOut, Box::new(MoveBy(1.0, 0.0, -100.0)))),
        Wait(0.5),
        Action(Ease(EaseFunction::ExponentialInOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Blink(1.0, 5)),
        While(Box::new(WaitForever), vec![
            Action(Ease(EaseFunction::QuadraticIn, Box::new(FadeOut(1.0)))),
            Action(Ease(EaseFunction::QuadraticOut, Box::new(FadeIn(1.0)))),
        ]),
    ]);
    scene.run(id.clone(), &seq);

    // This animation and the one above can run in parallel.
    let rotate = Action(Ease(EaseFunction::ExponentialInOut,
        Box::new(RotateTo(2.0, 360.0))));
    scene.run(id.clone(), &rotate);

    println!("Press any key to pause/resume the animation!");

    let ref mut gl = GlGraphics::new(opengl);
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;

        scene.event(&e);

        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([1.0, 1.0, 1.0, 1.0], gl);
                scene.draw(c.transform, gl);
            });
        }
        if let Some(_) = e.press_args() {
            scene.toggle(id.clone(), &seq);
            scene.toggle(id.clone(), &rotate);
        }
    }
}
<commit_msg>fixed example to pass uuid by ref<commit_after>extern crate piston;
extern crate ai_behavior;
extern crate sprite;
extern crate graphics;
extern crate sdl2_window;
extern crate opengl_graphics;

use std::path::Path;
use std::cell::RefCell;
use std::rc::Rc;

use sprite::*;
use ai_behavior::{
    Action,
    Sequence,
    Wait,
    WaitForever,
    While,
};

use sdl2_window::Sdl2Window;
use opengl_graphics::{
    GlGraphics,
    OpenGL,
    Texture,
};

fn main() {
    let (width, height) = (300, 300);
    let opengl = OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        piston::window::WindowSettings {
            title: "piston-example-sprite".to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let id;
    let mut scene = Scene::new();
    let tex = Path::new("./bin/assets/rust-logo.png");
    let tex = Rc::new(Texture::from_path(&tex).unwrap());
    let mut sprite = Sprite::from_texture(tex.clone());
    sprite.set_position(width as f64 / 2.0, height as f64 / 2.0);

    id = scene.add_child(sprite);

    // Run a sequence or animations.
    let seq = Sequence(vec![
        Action(Ease(EaseFunction::CubicOut, Box::new(ScaleTo(2.0, 0.5, 0.5)))),
        Action(Ease(EaseFunction::BounceOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Ease(EaseFunction::ElasticOut, Box::new(MoveBy(2.0, 0.0, -100.0)))),
        Action(Ease(EaseFunction::BackInOut, Box::new(MoveBy(1.0, 0.0, -100.0)))),
        Wait(0.5),
        Action(Ease(EaseFunction::ExponentialInOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Blink(1.0, 5)),
        While(Box::new(WaitForever), vec![
            Action(Ease(EaseFunction::QuadraticIn, Box::new(FadeOut(1.0)))),
            Action(Ease(EaseFunction::QuadraticOut, Box::new(FadeIn(1.0)))),
        ]),
    ]);
    scene.run(&id, &seq);

    // This animation and the one above can run in parallel.
    let rotate = Action(Ease(EaseFunction::ExponentialInOut,
        Box::new(RotateTo(2.0, 360.0))));
    scene.run(&id, &rotate);

    println!("Press any key to pause/resume the animation!");

    let ref mut gl = GlGraphics::new(opengl);
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;

        scene.event(&e);

        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([1.0, 1.0, 1.0, 1.0], gl);
                scene.draw(c.transform, gl);
            });
        }
        if let Some(_) = e.press_args() {
            scene.toggle(&id, &seq);
            scene.toggle(&id, &rotate);
        }
    }
}
<|endoftext|>