<commit_before>//! This is a very early work-in-progress binding to various Linux Kernel APIs.

#![cfg(target_os="linux")]

//Start allowing warnings that are unavoidable
#![allow(non_camel_case_types)]
#![allow(dead_code)]

//Okay, let's import our internal modules
pub mod cstdlib;
pub mod posix_types;
pub mod time;

pub use std::os::*;
pub use std::os::raw::*;
pub use std::os::linux::raw::*; //Needed for time_t, dev_t, etc

//And re-export our modules
pub use cstdlib::*;
pub use posix_types::*;
pub use time::*;

#[cfg(test)]
mod tests {

    #[allow(unused_variables)]
    #[test]
    fn ensure_types_exist() {
        let schar: ::c_schar = -3;
        let uchar: ::c_uchar = 2;
        let achar: ::c_char = 62;

        let ashort: ::c_short = -5162;
        let ushort: ::c_ushort = 65000;

        let aint: ::c_int = 26327;
        let uint: ::c_uint = 20000026;

        let long: ::c_long = 75473765327;
        let ulong: ::c_ulong = 26294762868676748;

        let float: ::c_float = 2462347.426f32;
        let double: ::c_double = 2694237684327.4326237637f64;

        let dev: ::dev_t = 12467;
        let mode: ::mode_t = 1365236;
        let time: ::time_t = 134062;

        assert!(true);//Well, we haven't crashed! I guess it worked
    }

}
<commit_msg>Add get_last_error_number()<commit_after>//! This is a very early work-in-progress binding to various Linux Kernel APIs.

#![cfg(target_os="linux")]

//Start allowing warnings that are unavoidable
#![allow(non_camel_case_types)]
#![allow(dead_code)]

//Okay, let's import our internal modules
pub mod cstdlib;
pub mod posix_types;
pub mod time;

pub use std::os::*;
pub use std::os::raw::*;
pub use std::os::linux::raw::*; //Needed for time_t, dev_t, etc

//And re-export our modules
pub use cstdlib::*;
pub use posix_types::*;
pub use time::*;

extern {

    //pub fn syscall(num: ::c_long, ...) -> ::c_int; TODO: Check this, exit() does not work via syscall. Check branch `unistd-syscall-rewrite`

    ///Gets the pointer of the last error number's location
    pub fn __errno_location() -> *mut ::c_int;

}

///Gets the last error number
pub fn get_last_error_number() -> ::c_int {

    unsafe {
        let pointer = __errno_location();

        return ::std::ptr::read(pointer);
    }

}

#[cfg(test)]
mod tests {

    #[test]
    fn no_errors_means_no_stupid_error() {
        assert_eq!(0, ::get_last_error_number());
    }

    #[allow(unused_variables)]
    #[test]
    fn ensure_types_exist() {
        let schar: ::c_schar = -3;
        let uchar: ::c_uchar = 2;
        let achar: ::c_char = 62;

        let ashort: ::c_short = -5162;
        let ushort: ::c_ushort = 65000;

        let aint: ::c_int = 26327;
        let uint: ::c_uint = 20000026;

        let long: ::c_long = 75473765327;
        let ulong: ::c_ulong = 26294762868676748;

        let float: ::c_float = 2462347.426f32;
        let double: ::c_double = 2694237684327.4326237637f64;

        let dev: ::dev_t = 12467;
        let mode: ::mode_t = 1365236;
        let time: ::time_t = 134062;

        assert!(true);//Well, we haven't crashed! I guess it worked
    }

}
<|endoftext|>


<commit_before>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern crate wordcut_engine;

use std::path::Path;
use std::io::Result;
use self::wordcut_engine::Dict;

pub type Wordcut = self::wordcut_engine::Wordcut;

pub fn default_path() -> &'static Path {
    Path::new(
        concat!(env!("CARGO_MANIFEST_DIR"),
                "/data/thai.txt"))
}

pub fn lao_path() -> &'static Path {
    Path::new(
        concat!(env!("CARGO_MANIFEST_DIR"),
                "/data/laowords.txt"))
}

pub fn load_dict(path: &Path) -> Result<Dict> {
    self::wordcut_engine::load_dict(path)
}

#[cfg(test)]
mod tests {
    use std::path::Path;
    use super::wordcut_engine::TextRange;
    use super::Wordcut;

    #[test]
    fn test_default_dict() {
        let dict = super::load_dict(super::default_path());
        assert!(dict.is_ok());
    }

    #[test]
    fn test_segment_into_ranges() {
        let dict = super::load_dict(Path::new("data/thai.txt")).unwrap();
        let wordcut = Wordcut::new(dict);
        let ranges = wordcut.segment("กากกา");
        let expected = vec![TextRange{s:0,e:3}, TextRange{s:3,e:5}];
        assert_eq!(ranges, expected)
    }

    #[test]
    fn test_segment_into_strings() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กากกา");
        let expected = vec!["กาก".to_string(), "กา".to_string()];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_punc() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("\"ฆกากา\"");
        let expected = &vec!["\"", "ฆ", "กา", "กา", "\"",]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_parentheses() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"(ฆกากา)".to_string());
        let expected = &vec!["(", "ฆ", "กา", "กา", ")",]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_unicode_quote() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("“ฆกากา”");
        let expected = &vec!["“", "ฆ", "กา", "กา", "”",]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_unknown_sandwich() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮกาฮฮ");
        let expected = &vec!["ฮฮ", "กา", "ฮฮ"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กา  มา");
        let expected = &vec!["กา", "  ", "มา"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces_unk() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮ  ญญ");
        let expected = &vec!["ฮฮ", "  ", "ญญ"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_one_word() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา");
        let expected = &vec!["มาตรา"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_from_law() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา 482 ผู้ขายไม่");
        let expected = &vec!["มาตรา", " ", "482", " ", "ผู้", "ขาย", "ไม่"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_space() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment("a cat");
        let expected = vec![TextRange{s:0,e:1},TextRange{s:1,e:2},TextRange{s:2,e:5}];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_lao() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment(&"ພາສາລາວມີ".to_string());
        let expected = vec![TextRange{s:0,e:4},TextRange{s:4,e:7},TextRange{s:7,e:9}];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_latin() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"ฑฑACญญ".to_string());
        let expected = &vec!["ฑฑ", "AC", "ญญ"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

}
<commit_msg>Add cargo_dir<commit_after>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern crate wordcut_engine;

use std::path::Path;
use std::io::Result;
use self::wordcut_engine::Dict;

pub type Wordcut = self::wordcut_engine::Wordcut;

pub fn cargo_dir() -> &'static Path {
    Path::new(env!("CARGO_MANIFEST_DIR"))
}

pub fn default_path() -> &'static Path {
    Path::new(
        concat!(env!("CARGO_MANIFEST_DIR"),
                "/data/thai.txt"))
}

pub fn lao_path() -> &'static Path {
    Path::new(
        concat!(env!("CARGO_MANIFEST_DIR"),
                "/data/laowords.txt"))
}

pub fn load_dict(path: &Path) -> Result<Dict> {
    self::wordcut_engine::load_dict(path)
}

#[cfg(test)]
mod tests {
    use std::path::Path;
    use super::wordcut_engine::TextRange;
    use super::Wordcut;

    #[test]
    fn test_default_dict() {
        let dict = super::load_dict(super::default_path());
        assert!(dict.is_ok());
    }

    #[test]
    fn test_segment_into_ranges() {
        let dict = super::load_dict(Path::new("data/thai.txt")).unwrap();
        let wordcut = Wordcut::new(dict);
        let ranges = wordcut.segment("กากกา");
        let expected = vec![TextRange{s:0,e:3}, TextRange{s:3,e:5}];
        assert_eq!(ranges, expected)
    }

    #[test]
    fn test_segment_into_strings() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กากกา");
        let expected = vec!["กาก".to_string(), "กา".to_string()];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_punc() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("\"ฆกากา\"");
        let expected = &vec!["\"", "ฆ", "กา", "กา", "\"",]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_parentheses() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"(ฆกากา)".to_string());
        let expected = &vec!["(", "ฆ", "กา", "กา", ")",]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_unicode_quote() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("“ฆกากา”");
        let expected = &vec!["“", "ฆ", "กา", "กา", "”",]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_unknown_sandwich() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮกาฮฮ");
        let expected = &vec!["ฮฮ", "กา", "ฮฮ"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กา  มา");
        let expected = &vec!["กา", "  ", "มา"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces_unk() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮ  ญญ");
        let expected = &vec!["ฮฮ", "  ", "ญญ"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_one_word() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา");
        let expected = &vec!["มาตรา"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_from_law() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา 482 ผู้ขายไม่");
        let expected = &vec!["มาตรา", " ", "482", " ", "ผู้", "ขาย", "ไม่"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_space() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment("a cat");
        let expected = vec![TextRange{s:0,e:1},TextRange{s:1,e:2},TextRange{s:2,e:5}];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_lao() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment(&"ພາສາລາວມີ".to_string());
        let expected = vec![TextRange{s:0,e:4},TextRange{s:4,e:7},TextRange{s:7,e:9}];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_latin() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"ฑฑACญญ".to_string());
        let expected = &vec!["ฑฑ", "AC", "ญญ"]
            .iter()
            .map(|&s| s.to_string()).collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_get_cargo_dir() {
	let cargo_dir = super::cargo_dir().to_str().unwrap();
	assert!(cargo_dir.find(".cargo").is_some());
    }
}

<|endoftext|>


<commit_before>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test

#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![feature(core)]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

extern crate "rustc-serialize" as rustc_serialize;

use std::collections::BTreeMap;
use std::str::FromStr;
use std::string;

pub use parser::{Parser, ParserError};
pub use serialization::{Encoder, encode, encode_str};
pub use serialization::{Decoder, decode, decode_str};
pub use serialization::Error;
pub use serialization::Error::{NeedsKey, NoValue};
pub use serialization::Error::{InvalidMapKeyLocation, InvalidMapKeyType};
pub use serialization::{DecodeError, DecodeErrorKind};
pub use serialization::DecodeErrorKind::{ApplicationError, ExpectedField};
pub use serialization::DecodeErrorKind::{ExpectedMapElement, ExpectedMapKey, NoEnumVariants};
pub use serialization::DecodeErrorKind::{ExpectedType, NilTooLong};

mod parser;
mod display;
mod serialization;

/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
    String(string::String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(string::String),
    Array(Array),
    Table(Table),
}

/// Type representing a TOML array, payload of the Value::Array variant
pub type Array = Vec<Value>;

/// Type representing a TOML table, payload of the Value::Table variant
pub type Table = BTreeMap<string::String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::String(..), &Value::String(..)) |
            (&Value::Integer(..), &Value::Integer(..)) |
            (&Value::Float(..), &Value::Float(..)) |
            (&Value::Boolean(..), &Value::Boolean(..)) |
            (&Value::Datetime(..), &Value::Datetime(..)) |
            (&Value::Array(..), &Value::Array(..)) |
            (&Value::Table(..), &Value::Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            Value::String(..) => "string",
            Value::Integer(..) => "integer",
            Value::Float(..) => "float",
            Value::Boolean(..) => "boolean",
            Value::Datetime(..) => "datetime",
            Value::Array(..) => "array",
            Value::Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::String(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Value::Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Value::Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Value::Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Value::Array(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a Table> {
        match *self { Value::Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = toml.parse().unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        for key in path.split('.') {
            match cur_value {
                &Value::Table(ref hm) => {
                    match hm.get(key) {
                        Some(v) => cur_value = v,
                        None => return None
                    }
                },
                &Value::Array(ref v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    type Err = Vec<ParserError>;
    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
        let mut p = Parser::new(s);
        match p.parse().map(Value::Table) {
            Some(n) => Ok(n),
            None => Err(p.errors),
        }
    }
}

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

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        assert!(value.lookup("test.bar").is_none());
        assert!(value.lookup("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = toml.parse().unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }
}
<commit_msg>Implement Encodable for Value<commit_after>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test

#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![feature(core)]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

extern crate "rustc-serialize" as rustc_serialize;

use std::collections::BTreeMap;
use std::str::FromStr;
use std::string;

pub use parser::{Parser, ParserError};
pub use serialization::{Encoder, encode, encode_str};
pub use serialization::{Decoder, decode, decode_str};
pub use serialization::Error;
pub use serialization::Error::{NeedsKey, NoValue};
pub use serialization::Error::{InvalidMapKeyLocation, InvalidMapKeyType};
pub use serialization::{DecodeError, DecodeErrorKind};
pub use serialization::DecodeErrorKind::{ApplicationError, ExpectedField};
pub use serialization::DecodeErrorKind::{ExpectedMapElement, ExpectedMapKey, NoEnumVariants};
pub use serialization::DecodeErrorKind::{ExpectedType, NilTooLong};

mod parser;
mod display;
mod serialization;

/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

/// Type representing a TOML array, payload of the Value::Array variant
pub type Array = Vec<Value>;

/// Type representing a TOML table, payload of the Value::Table variant
pub type Table = BTreeMap<string::String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::String(..), &Value::String(..)) |
            (&Value::Integer(..), &Value::Integer(..)) |
            (&Value::Float(..), &Value::Float(..)) |
            (&Value::Boolean(..), &Value::Boolean(..)) |
            (&Value::Datetime(..), &Value::Datetime(..)) |
            (&Value::Array(..), &Value::Array(..)) |
            (&Value::Table(..), &Value::Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            Value::String(..) => "string",
            Value::Integer(..) => "integer",
            Value::Float(..) => "float",
            Value::Boolean(..) => "boolean",
            Value::Datetime(..) => "datetime",
            Value::Array(..) => "array",
            Value::Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::String(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Value::Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Value::Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Value::Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Value::Array(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a Table> {
        match *self { Value::Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = toml.parse().unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        for key in path.split('.') {
            match cur_value {
                &Value::Table(ref hm) => {
                    match hm.get(key) {
                        Some(v) => cur_value = v,
                        None => return None
                    }
                },
                &Value::Array(ref v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl rustc_serialize::Encodable for Value {
    fn encode<E>(&self, e: &mut E) -> Result<(), E::Error>
        where E: rustc_serialize::Encoder
    {
        match *self {
            Value::String(ref s) => e.emit_str(s),
            Value::Integer(i) => e.emit_i64(i),
            Value::Float(f) => e.emit_f64(f),
            Value::Boolean(b) => e.emit_bool(b),
            Value::Datetime(ref s) => e.emit_str(s),
            Value::Array(ref a) => {
                e.emit_seq(a.len(), |e| {
                    for item in a {
                        try!(item.encode(e));
                    }
                    Ok(())
                })
            }
            Value::Table(ref t) => {
                e.emit_map(t.len(), |e| {
                    for (i, (key, value)) in t.iter().enumerate() {
                        try!(e.emit_map_elt_key(i, |e| e.emit_str(key)));
                        try!(e.emit_map_elt_val(i, |e| value.encode(e)));
                    }
                    Ok(())
                })
            }
        }
    }
}

impl FromStr for Value {
    type Err = Vec<ParserError>;
    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
        let mut p = Parser::new(s);
        match p.parse().map(Value::Table) {
            Some(n) => Ok(n),
            None => Err(p.errors),
        }
    }
}

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

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        assert!(value.lookup("test.bar").is_none());
        assert!(value.lookup("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = toml.parse().unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }

    #[test]
    fn round_trip() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();
        let val2 = ::encode_str(&value).parse().unwrap();
        assert_eq!(value, val2);
    }
}
<|endoftext|>


<commit_before>extern crate ucd_raw;

use std::fs::File;
use std::io::Write;
use std::time::Instant;
use ucd_raw::Character;
use ucd_raw::CHARACTERS;

#[derive(Debug)]
struct Entry {
    index: usize,
    codepoint: u32,
}

#[derive(Debug)]
struct TempSuffix<'a> {
    suffix: &'a str,
    entry: Entry,
}

fn suffixes<'a>(string: &'a str) -> impl Iterator<Item = (usize, &'a str)> {
    (0..string.len()).map(move |i| &string[i..]).enumerate()
}

fn main() {
    let start = Instant::now();

    let mut combined = Vec::new();
    let mut temp_suffixes = Vec::new();

    let mut out = File::create("src/generated.rs").unwrap();

    for character in char_iter().take(20) {
        let start = combined.len();

        for byte in character.name.bytes() {
            combined.push(byte);
        }
        combined.push(b'\n');

        for (offset, suffix) in suffixes(character.name) {
            temp_suffixes.push(TempSuffix {
                suffix,
                entry: Entry {
                    index: start + offset,
                    codepoint: character.codepoint,
                },
            });
        }
    }

    temp_suffixes.sort_by_key(|temp_suffix| temp_suffix.suffix);

    writeln!(out, "use table::Entry;").unwrap();

    writeln!(
        out,
        "pub const ENTRIES: &[Entry] = &{:#?};",
        temp_suffixes
            .into_iter()
            .map(|temp_suffix| temp_suffix.entry)
            .collect::<Vec<_>>()
    ).unwrap();

    writeln!(
        out,
        "pub const COMBINED: &[u8] = b\"{}\";",
        String::from_utf8(combined).unwrap()
    ).unwrap();

    println!("Generated in {:?}", start.elapsed());
}

fn char_iter() -> impl Iterator<Item = &'static Character> {
    CHARACTERS
        .iter()
        .filter(|character| match character.codepoint {
            0x03400...0x04DB5 => false,
            0x04E00...0x09FEA => false,
            0x20000...0x2A6D6 => false,
            0x2A700...0x2B734 => false,
            0x2B740...0x2B81D => false,
            0x2B820...0x2CEA1 => false,
            0x2CEB0...0x2EBE0 => false,
            0x17000...0x187EC => false,
            0x1B170...0x1B2FB => false,
            0x0F900...0x0FA6D => false,
            0x0FA70...0x0FAD9 => false,
            0x2F800...0x2FA1D => false,
            _ => true,
        })
}
<commit_msg>Deduplicate index<commit_after>extern crate ucd_raw;

use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::time::Instant;
use ucd_raw::Character;
use ucd_raw::CHARACTERS;

#[derive(Debug)]
struct Entry {
    index: usize,
    codepoints: Vec<u32>,
}

#[derive(Debug)]
struct TempSuffix<'a> {
    suffix: &'a str,
    entry: Entry,
}

fn char_iter() -> impl Iterator<Item = &'static Character> {
    CHARACTERS
        .iter()
        .filter(|character| match character.codepoint {
            0x03400...0x04DB5 => false,
            0x04E00...0x09FEA => false,
            0x20000...0x2A6D6 => false,
            0x2A700...0x2B734 => false,
            0x2B740...0x2B81D => false,
            0x2B820...0x2CEA1 => false,
            0x2CEB0...0x2EBE0 => false,
            0x17000...0x187EC => false,
            0x1B170...0x1B2FB => false,
            0x0F900...0x0FA6D => false,
            0x0FA70...0x0FAD9 => false,
            0x2F800...0x2FA1D => false,
            _ => true,
        })
}

fn suffixes<'a>(string: &'a str) -> impl Iterator<Item = (usize, &'a str)> {
    (0..string.len()).map(move |i| &string[i..]).enumerate()
}

fn main() {
    let start = Instant::now();

    let mut combined = String::new();
    let mut visited_words = HashMap::new();
    let mut temp_suffixes = Vec::new();

    let mut out = File::create("src/generated.rs").unwrap();

    for character in char_iter().take(20) {
        for word in character.name.split_whitespace() {
            let mut start;

            if visited_words.contains_key(word) {
                start = visited_words[word];
            } else {
                start = combined.len();

                visited_words.insert(word, start);
                combined.push_str(word);
                combined.push('\n');
            }

            for (offset, suffix) in suffixes(word) {
                temp_suffixes.push(TempSuffix {
                    suffix,
                    entry: Entry {
                        index: start + offset,
                        codepoints: vec![character.codepoint],
                    },
                });
            }
        }
    }

    temp_suffixes.sort_by_key(|temp_suffix| temp_suffix.suffix);
    temp_suffixes.dedup_by(|a, b| {
        let equal = a.suffix == b.suffix;

        if equal {
            b.entry.codepoints.extend_from_slice(&a.entry.codepoints);
        }

        equal
    });

    writeln!(out, "// Auto-generated by `src/bin/gen`\n").unwrap();
    writeln!(out, "use table::Entry;").unwrap();

    writeln!(
        out,
        "pub const ENTRIES: &[Entry] = &{:#?};",
        temp_suffixes
            // .into_iter()
            // .map(|temp_suffix| temp_suffix.entry)
            // .collect::<Vec<_>>()
    ).unwrap();

    writeln!(out, "pub const COMBINED: &[u8] = b\"{}\";", combined).unwrap();

    println!("Generated in {:?}", start.elapsed());
}
<|endoftext|>


<commit_before>//! Logging module

extern crate time;
use std::collections::vec_deque::VecDeque;
use std::fmt;
use std::io::{Write, Read, Seek, BufRead};
use std;

pub enum FilterLog {
    None,
    Last(time::Tm)
}

impl FilterLog {
    ///Checks if given element is within allowed time range
    #[inline]
    pub fn check(&self, time: &time::Tm) -> bool {
        match *self {
            FilterLog::None => true,
            FilterLog::Last(from) => from > *time,
        }
    }
}

impl fmt::Display for FilterLog {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            FilterLog::None => write!(f, "None"),
            FilterLog::Last(from) => write!(f, "Last({})", from.strftime("%X.%f").unwrap()),
        }
    }
}

pub struct IrcLog {
    inner: VecDeque<IrcEntry>,
    fs_buf: std::fs::File
}

impl IrcLog {
    /// Creates log with default capacity 500.
    #[inline(always)]
    pub fn new() -> IrcLog {
        IrcLog {
            inner: VecDeque::with_capacity(500),
            //Open file log once for both write/read.
            //To read/write correctly be sure to .seek() at needed position
            fs_buf: std::fs::OpenOptions::new().read(true)
                                               .write(true)
                                               .create(true)
                                               .open("vndis.log")
                                               .unwrap()
        }
    }

    ///Dumps all logs except for last 20
    pub fn dump_to_fs(&mut self) {
        let len = self.inner.len();

        if len <= 20 {return;}

        self.fs_buf.seek(std::io::SeekFrom::End(0)).unwrap();
        //range is exclusive at the end
        for _ in 0..len-19 {
            self.fs_buf.write_fmt(format_args!("{}\n", self.inner.pop_front().unwrap())).unwrap();
        }
        self.fs_buf.flush().unwrap()
    }

    #[inline(always)]
    /// Adds entry to log.
    pub fn add(&mut self, entry: IrcEntry) {
        if self.inner.len() >= self.inner.capacity() {
            self.dump_to_fs();
        }
        self.inner.push_back(entry);
    }

    #[inline]
    /// Reads all/filtered entries from underlying file buffer.
    pub fn fs_read(&mut self, filter: &FilterLog) -> String {
        self.fs_buf.seek(std::io::SeekFrom::Start(0)).unwrap();

        let reader = std::io::BufReader::new(&mut self.fs_buf);
        let lines = reader.lines();

        //Let's try to peek the number of lines for effective allocation
        let acc_str = if let (_, Some(len)) = lines.size_hint() {
            String::with_capacity(len*50)
        }
        else {
            String::new()
        };

        lines.fold(acc_str, |acc, line| {
            const DATA_START: usize = 1;
            const DATA_END: usize = 28;
            let line = line.unwrap();
            let time_stamp = time::strptime(&line[DATA_START..DATA_END], "%x %X.%f").unwrap();

            if filter.check(&time_stamp) {
                acc + &format!("{}\n", line)
            }
            else {
                acc
            }
        })
    }

    #[inline(always)]
    /// Returns iterator over underlying buffer.
    pub fn iter(&self) -> std::collections::vec_deque::Iter<IrcEntry> {
        self.inner.iter()
    }

    #[inline(always)]
    pub fn back(&self) -> Option<&IrcEntry> {
        self.inner.back()
    }

    #[inline(always)]
    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

#[derive(Clone, Debug)]
pub struct IrcEntry {
    time: time::Tm,
    nickname: String,
    message: String
}

impl IrcEntry {
    #[inline(always)]
    /// Creates new log entry from message and nick
    pub fn new(nick: String, msg: String) -> IrcEntry {
        IrcEntry {
            time: time::now(),
            nickname: nick,
            message: msg,
        }
    }

    #[inline(always)]
    pub fn time(&self) -> time::Tm {
        self.time
    }
}

impl PartialEq for IrcEntry {
    fn eq(&self, right: &IrcEntry) -> bool {
        self.time == right.time
    }

    fn ne(&self, right: &IrcEntry) -> bool {
        self.time != right.time
    }
}

impl fmt::Display for IrcEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "[{}] <{}> {}", self.time.strftime("%x %X.%f").unwrap(), self.nickname, self.message)
    }
}
<commit_msg>correct display of filter<commit_after>//! Logging module

extern crate time;
use std::collections::vec_deque::VecDeque;
use std::fmt;
use std::io::{Write, Read, Seek, BufRead};
use std;

pub enum FilterLog {
    None,
    Last(time::Tm)
}

impl FilterLog {
    ///Checks if given element is within allowed time range
    #[inline]
    pub fn check(&self, time: &time::Tm) -> bool {
        match *self {
            FilterLog::None => true,
            FilterLog::Last(from) => from > *time,
        }
    }
}

impl fmt::Display for FilterLog {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            FilterLog::None => write!(f, "None"),
            FilterLog::Last(from) => write!(f, "Last({})", from.strftime("%x %X.%f").unwrap()),
        }
    }
}

pub struct IrcLog {
    inner: VecDeque<IrcEntry>,
    fs_buf: std::fs::File
}

impl IrcLog {
    /// Creates log with default capacity 500.
    #[inline(always)]
    pub fn new() -> IrcLog {
        IrcLog {
            inner: VecDeque::with_capacity(500),
            //Open file log once for both write/read.
            //To read/write correctly be sure to .seek() at needed position
            fs_buf: std::fs::OpenOptions::new().read(true)
                                               .write(true)
                                               .create(true)
                                               .open("vndis.log")
                                               .unwrap()
        }
    }

    ///Dumps all logs except for last 20
    pub fn dump_to_fs(&mut self) {
        let len = self.inner.len();

        if len <= 20 {return;}

        self.fs_buf.seek(std::io::SeekFrom::End(0)).unwrap();
        //range is exclusive at the end
        for _ in 0..len-19 {
            self.fs_buf.write_fmt(format_args!("{}\n", self.inner.pop_front().unwrap())).unwrap();
        }
        self.fs_buf.flush().unwrap()
    }

    #[inline(always)]
    /// Adds entry to log.
    pub fn add(&mut self, entry: IrcEntry) {
        if self.inner.len() >= self.inner.capacity() {
            self.dump_to_fs();
        }
        self.inner.push_back(entry);
    }

    #[inline]
    /// Reads all/filtered entries from underlying file buffer.
    pub fn fs_read(&mut self, filter: &FilterLog) -> String {
        self.fs_buf.seek(std::io::SeekFrom::Start(0)).unwrap();

        let reader = std::io::BufReader::new(&mut self.fs_buf);
        let lines = reader.lines();

        //Let's try to peek the number of lines for effective allocation
        let acc_str = if let (_, Some(len)) = lines.size_hint() {
            String::with_capacity(len*50)
        }
        else {
            String::new()
        };

        lines.fold(acc_str, |acc, line| {
            const DATA_START: usize = 1;
            const DATA_END: usize = 28;
            let line = line.unwrap();
            let time_stamp = time::strptime(&line[DATA_START..DATA_END], "%x %X.%f").unwrap();

            if filter.check(&time_stamp) {
                acc + &format!("{}\n", line)
            }
            else {
                acc
            }
        })
    }

    #[inline(always)]
    /// Returns iterator over underlying buffer.
    pub fn iter(&self) -> std::collections::vec_deque::Iter<IrcEntry> {
        self.inner.iter()
    }

    #[inline(always)]
    pub fn back(&self) -> Option<&IrcEntry> {
        self.inner.back()
    }

    #[inline(always)]
    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

#[derive(Clone, Debug)]
pub struct IrcEntry {
    time: time::Tm,
    nickname: String,
    message: String
}

impl IrcEntry {
    #[inline(always)]
    /// Creates new log entry from message and nick
    pub fn new(nick: String, msg: String) -> IrcEntry {
        IrcEntry {
            time: time::now(),
            nickname: nick,
            message: msg,
        }
    }

    #[inline(always)]
    pub fn time(&self) -> time::Tm {
        self.time
    }
}

impl PartialEq for IrcEntry {
    fn eq(&self, right: &IrcEntry) -> bool {
        self.time == right.time
    }

    fn ne(&self, right: &IrcEntry) -> bool {
        self.time != right.time
    }
}

impl fmt::Display for IrcEntry {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "[{}] <{}> {}", self.time.strftime("%x %X.%f").unwrap(), self.nickname, self.message)
    }
}
<|endoftext|>


<commit_before>//! byt
//!
//! This library provides a way to initialize an instance of byt.
//!
//! In the future it'd be good if this included a way to change the
//! default file descriptors for STDOUT/STDERR. Then you could run
//! automated tests just by piping in a file.

// EXTERNS
extern crate libc;

// LIBRARY INCLUDES
use std::thread;
use std::sync::mpsc;
use std::sync::{Arc,Mutex};

// SUBMODULES
mod render;
mod brain;

// LOCAL INCLUDES
use byt::render::*;
use byt::brain::*;

/// Initialize and start byt.
pub fn init() {
    // Mutex for the current rendering size
    let data = Arc::new(Mutex::new(Point { row : 0, col : 0}));
    // Channel for communication to the renderer.
    let (tx, rx) = mpsc::channel();

    // Start the brain thread
    {
        let tx = tx.clone();
        let data = data.clone();

        thread::spawn(move || { brain_thread(tx, data); });
    }

    // Start the rendering thread
    thread::spawn(move || { render_thread(rx, data); });

    loop {}
}
<commit_msg>fix(init): don't spinwait<commit_after>//! byt
//!
//! This library provides a way to initialize an instance of byt.
//!
//! In the future it'd be good if this included a way to change the
//! default file descriptors for STDOUT/STDERR. Then you could run
//! automated tests just by piping in a file.

// EXTERNS
extern crate libc;

// LIBRARY INCLUDES
use std::thread;
use std::sync::mpsc;
use std::sync::{Arc,Mutex};

// SUBMODULES
mod render;
mod brain;

// LOCAL INCLUDES
use byt::render::*;
use byt::brain::*;

/// Initialize and start byt.
pub fn init() {
    // Mutex for the current rendering size
    let data = Arc::new(Mutex::new(Point { row : 0, col : 0}));
    // Channel for communication to the renderer.
    let (tx, rx) = mpsc::channel();

    // Start the brain thread
    {
        let tx = tx.clone();
        let data = data.clone();

        thread::spawn(move || { brain_thread(tx, data); });
    }

    // Start the rendering thread
    let render = thread::spawn(move || { render_thread(rx, data); });

    render.join();
}
<|endoftext|>


<commit_before>mod raft_log;
pub mod storage;
mod raft;
mod progress;
mod errors;
mod log_unstable;
mod status;
pub mod raw_node;

pub use self::storage::{RaftState, Storage};
pub use self::errors::{Result, Error, StorageError};
pub use self::raft::{Raft, StateRole, Config, INVALID_ID, SoftState};
pub use self::raft_log::{RaftLog, NO_LIMIT};
pub use self::raw_node::{Ready, RawNode, Peer, is_empty_snap};
pub use self::status::Status;
pub use self::log_unstable::Unstable;
pub use self::progress::{Inflights, Progress, ProgressState};
<commit_msg>raft: public SnapshotStatus.<commit_after>mod raft_log;
pub mod storage;
mod raft;
mod progress;
mod errors;
mod log_unstable;
mod status;
pub mod raw_node;

pub use self::storage::{RaftState, Storage};
pub use self::errors::{Result, Error, StorageError};
pub use self::raft::{Raft, StateRole, Config, INVALID_ID, SoftState};
pub use self::raft_log::{RaftLog, NO_LIMIT};
pub use self::raw_node::{Ready, RawNode, Peer, is_empty_snap, SnapshotStatus};
pub use self::status::Status;
pub use self::log_unstable::Unstable;
pub use self::progress::{Inflights, Progress, ProgressState};
<|endoftext|>


<commit_before>#![feature(used)]
#![no_std]
extern crate cortex_m;
extern crate stm32f0_hal as hal;

use hal::rcc;
use hal::uart;

fn main() {
    rcc::init(); // Full Speed 48Mhz
    uart::init(
        6000000,
        uart::NBits::_8bits,
        uart::StopBits::_1b,
        uart::Parity::None,
    );
    loop {
        if uart::transmit_complete() {
            uart::send(0x55);
        }
    }
}
<commit_msg>Update uart example<commit_after>#![feature(used)]
#![no_std]
extern crate cortex_m;
extern crate stm32f0_hal as hal;

use hal::rcc;
use hal::uart;

fn main() {
    rcc::init(); // Full Speed 48Mhz
    uart::setup(
        6000000,
        uart::NBits::_8bits,
        uart::StopBits::_1b,
        uart::Parity::None,
        |byte| uart::send(byte),
    );
    if uart::transmit_complete() {
        uart::send(0x55);
    }
    loop {

    }
}
<|endoftext|>


<commit_before>use types::*;

use nom::{be_i8, be_u8, be_i16, be_u16, be_i32, be_u32, be_i64, be_u64, be_f32, be_f64};

/* FIXME: we convert to a Some so that nom can happily handle some _ case which would otherwise fail as we're exhaustive */
named!(pub parse_value<AMQPValue>,                 switch!(map!(parse_type, |t| Some(t)),
    Some(AMQPType::Boolean)        => map!(call!(parse_boolean),          |b| AMQPValue::Boolean(b))        |
    Some(AMQPType::ShortShortInt)  => map!(call!(parse_short_short_int),  |i| AMQPValue::ShortShortInt(i))  |
    Some(AMQPType::ShortShortUInt) => map!(call!(parse_short_short_uint), |u| AMQPValue::ShortShortUInt(u)) |
    Some(AMQPType::ShortInt)       => map!(call!(parse_short_int),        |i| AMQPValue::ShortInt(i))       |
    Some(AMQPType::ShortUInt)      => map!(call!(parse_short_uint),       |u| AMQPValue::ShortUInt(u))      |
    Some(AMQPType::LongInt)        => map!(call!(parse_long_int),         |i| AMQPValue::LongInt(i))        |
    Some(AMQPType::LongUInt)       => map!(call!(parse_long_uint),        |u| AMQPValue::LongUInt(u))       |
    Some(AMQPType::LongLongInt)    => map!(call!(parse_long_long_int),    |i| AMQPValue::LongLongInt(i))    |
    Some(AMQPType::LongLongUInt)   => map!(call!(parse_long_long_uint),   |u| AMQPValue::LongLongUInt(u))   |
    Some(AMQPType::Float)          => map!(call!(parse_float),            |f| AMQPValue::Float(f))          |
    Some(AMQPType::Double)         => map!(call!(parse_double),           |d| AMQPValue::Double(d))         |
    Some(AMQPType::DecimalValue)   => map!(call!(parse_decimal_value),    |d| AMQPValue::DecimalValue(d))   |
    Some(AMQPType::ShortString)    => map!(call!(parse_short_string),     |s| AMQPValue::ShortString(s))    |
    Some(AMQPType::LongString)     => map!(call!(parse_long_string),      |s| AMQPValue::LongString(s))     |
    Some(AMQPType::FieldArray)     => map!(call!(parse_field_array),      |a| AMQPValue::FieldArray(a))     |
    Some(AMQPType::Timestamp)      => map!(call!(parse_timestamp),        |t| AMQPValue::Timestamp(t))      |
    Some(AMQPType::FieldTable)     => map!(call!(parse_field_table),      |t| AMQPValue::FieldTable(t))     |
    Some(AMQPType::Void)           => value!(AMQPValue::Void)
));

named!(pub parse_type<AMQPType>,                   map_opt!(be_u8, |t| AMQPType::from_id(t as char)));

named!(pub parse_boolean<Boolean>,                 map!(be_u8, |b| b != 0));
named!(pub parse_short_short_int<ShortShortInt>,   call!(be_i8));
named!(pub parse_short_short_uint<ShortShortUInt>, call!(be_u8));
named!(pub parse_short_int<ShortInt>,              call!(be_i16));
named!(pub parse_short_uint<ShortUInt>,            call!(be_u16));
named!(pub parse_long_int<LongInt>,                call!(be_i32));
named!(pub parse_long_uint<LongUInt>,              call!(be_u32));
named!(pub parse_long_long_int<LongLongInt>,       call!(be_i64));
named!(pub parse_long_long_uint<LongLongUInt>,     call!(be_u64));
named!(pub parse_float<Float>,                     call!(be_f32));
named!(pub parse_double<Double>,                   call!(be_f64));
named!(pub parse_decimal_value<DecimalValue>,      do_parse!(scale: parse_short_short_uint >> value: parse_long_uint >> (DecimalValue { scale: scale, value: value, })));
named!(pub parse_short_string<ShortString>,        do_parse!(length: parse_short_short_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_long_string<LongString>,          do_parse!(length: parse_long_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_field_array<FieldArray>,          do_parse!(length: parse_long_int >> array: count!(parse_value, length as usize) >> (array)));
named!(pub parse_timestamp<Timestamp>,             call!(parse_long_long_uint));
named!(pub parse_field_table<FieldTable>,          do_parse!(length: parse_long_uint >> table: flat_map!(take!(length as usize), fold_many0!(complete!(pair!(parse_short_string, parse_value)), FieldTable::new(), |mut acc: FieldTable, (key, value)| {
    acc.insert(key, value);
    acc
})) >> (table)));

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

    use nom::IResult;

    const EMPTY: &'static [u8] = b"";

    #[test]
    fn test_parse_boolean() {
        assert_eq!(parse_boolean(&[0]), IResult::Done(EMPTY, false));
        assert_eq!(parse_boolean(&[1]), IResult::Done(EMPTY, true));
    }

    #[test]
    fn test_parse_short_short_uint() {
        assert_eq!(parse_short_short_uint(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_uint(&[255]), IResult::Done(EMPTY, 255));
    }

    #[test]
    fn test_parse_short_short_int() {
        assert_eq!(parse_short_short_int(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_int(&[255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_short_uint() {
        assert_eq!(parse_short_uint(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_uint(&[255, 255]), IResult::Done(EMPTY, 65535));
    }

    #[test]
    fn test_parse_short_int() {
        assert_eq!(parse_short_int(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_int(&[255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_uint() {
        assert_eq!(parse_long_uint(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_uint(&[255, 255, 255, 255]), IResult::Done(EMPTY, 4294967295));
    }

    #[test]
    fn test_parse_long_int() {
        assert_eq!(parse_long_int(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_int(&[255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_long_uint() {
        assert_eq!(parse_long_long_uint(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_uint(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_long_long_int() {
        assert_eq!(parse_long_long_int(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_int(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_float() {
        assert_eq!(parse_float(&[0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_float(&[42, 42, 42, 42]), IResult::Done(EMPTY, 0.00000000000015113662));
    }

    #[test]
    fn test_parse_double() {
        assert_eq!(parse_double(&[0,  0,  0,  0,  0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_double(&[42, 42, 42, 42, 42, 42, 42, 42]), IResult::Done(EMPTY, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014260258159703532));
    }

    #[test]
    fn test_parse_decimal_value() {
        assert_eq!(parse_decimal_value(&[0,   0,   0,   0,   0]),   IResult::Done(EMPTY, DecimalValue { scale: 0,   value: 0          }));
        assert_eq!(parse_decimal_value(&[255, 255, 255, 255, 255]), IResult::Done(EMPTY, DecimalValue { scale: 255, value: 4294967295 }));
    }

    #[test]
    fn test_parse_short_string() {
        assert_eq!(parse_short_string(&[0]),                                             IResult::Done(EMPTY, ShortString::new()));
        assert_eq!(parse_short_string(&[4, 't' as u8, 'e' as u8, 's' as u8, 't' as u8]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_long_string() {
        assert_eq!(parse_long_string(&[0, 0, 0, 0]),                                             IResult::Done(EMPTY, LongString::new()));
        assert_eq!(parse_long_string(&[0, 0, 0, 4, 't' as u8, 'e' as u8, 's' as u8, 't' as u8]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_timestamp() {
        assert_eq!(parse_timestamp(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_timestamp(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }
}
<commit_msg>types: add trivial parsing test<commit_after>use types::*;

use nom::{be_i8, be_u8, be_i16, be_u16, be_i32, be_u32, be_i64, be_u64, be_f32, be_f64};

/* FIXME: we convert to a Some so that nom can happily handle some _ case which would otherwise fail as we're exhaustive */
named!(pub parse_value<AMQPValue>,                 switch!(map!(parse_type, |t| Some(t)),
    Some(AMQPType::Boolean)        => map!(call!(parse_boolean),          |b| AMQPValue::Boolean(b))        |
    Some(AMQPType::ShortShortInt)  => map!(call!(parse_short_short_int),  |i| AMQPValue::ShortShortInt(i))  |
    Some(AMQPType::ShortShortUInt) => map!(call!(parse_short_short_uint), |u| AMQPValue::ShortShortUInt(u)) |
    Some(AMQPType::ShortInt)       => map!(call!(parse_short_int),        |i| AMQPValue::ShortInt(i))       |
    Some(AMQPType::ShortUInt)      => map!(call!(parse_short_uint),       |u| AMQPValue::ShortUInt(u))      |
    Some(AMQPType::LongInt)        => map!(call!(parse_long_int),         |i| AMQPValue::LongInt(i))        |
    Some(AMQPType::LongUInt)       => map!(call!(parse_long_uint),        |u| AMQPValue::LongUInt(u))       |
    Some(AMQPType::LongLongInt)    => map!(call!(parse_long_long_int),    |i| AMQPValue::LongLongInt(i))    |
    Some(AMQPType::LongLongUInt)   => map!(call!(parse_long_long_uint),   |u| AMQPValue::LongLongUInt(u))   |
    Some(AMQPType::Float)          => map!(call!(parse_float),            |f| AMQPValue::Float(f))          |
    Some(AMQPType::Double)         => map!(call!(parse_double),           |d| AMQPValue::Double(d))         |
    Some(AMQPType::DecimalValue)   => map!(call!(parse_decimal_value),    |d| AMQPValue::DecimalValue(d))   |
    Some(AMQPType::ShortString)    => map!(call!(parse_short_string),     |s| AMQPValue::ShortString(s))    |
    Some(AMQPType::LongString)     => map!(call!(parse_long_string),      |s| AMQPValue::LongString(s))     |
    Some(AMQPType::FieldArray)     => map!(call!(parse_field_array),      |a| AMQPValue::FieldArray(a))     |
    Some(AMQPType::Timestamp)      => map!(call!(parse_timestamp),        |t| AMQPValue::Timestamp(t))      |
    Some(AMQPType::FieldTable)     => map!(call!(parse_field_table),      |t| AMQPValue::FieldTable(t))     |
    Some(AMQPType::Void)           => value!(AMQPValue::Void)
));

named!(pub parse_type<AMQPType>,                   map_opt!(be_u8, |t| AMQPType::from_id(t as char)));

named!(pub parse_boolean<Boolean>,                 map!(be_u8, |b| b != 0));
named!(pub parse_short_short_int<ShortShortInt>,   call!(be_i8));
named!(pub parse_short_short_uint<ShortShortUInt>, call!(be_u8));
named!(pub parse_short_int<ShortInt>,              call!(be_i16));
named!(pub parse_short_uint<ShortUInt>,            call!(be_u16));
named!(pub parse_long_int<LongInt>,                call!(be_i32));
named!(pub parse_long_uint<LongUInt>,              call!(be_u32));
named!(pub parse_long_long_int<LongLongInt>,       call!(be_i64));
named!(pub parse_long_long_uint<LongLongUInt>,     call!(be_u64));
named!(pub parse_float<Float>,                     call!(be_f32));
named!(pub parse_double<Double>,                   call!(be_f64));
named!(pub parse_decimal_value<DecimalValue>,      do_parse!(scale: parse_short_short_uint >> value: parse_long_uint >> (DecimalValue { scale: scale, value: value, })));
named!(pub parse_short_string<ShortString>,        do_parse!(length: parse_short_short_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_long_string<LongString>,          do_parse!(length: parse_long_uint >> s: take_str!(length) >> (s.to_string())));
named!(pub parse_field_array<FieldArray>,          do_parse!(length: parse_long_int >> array: count!(parse_value, length as usize) >> (array)));
named!(pub parse_timestamp<Timestamp>,             call!(parse_long_long_uint));
named!(pub parse_field_table<FieldTable>,          do_parse!(length: parse_long_uint >> table: flat_map!(take!(length as usize), fold_many0!(complete!(pair!(parse_short_string, parse_value)), FieldTable::new(), |mut acc: FieldTable, (key, value)| {
    acc.insert(key, value);
    acc
})) >> (table)));

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

    use nom::IResult;

    const EMPTY: &'static [u8] = b"";

    #[test]
    fn test_parse_boolean() {
        assert_eq!(parse_boolean(&[0]), IResult::Done(EMPTY, false));
        assert_eq!(parse_boolean(&[1]), IResult::Done(EMPTY, true));
    }

    #[test]
    fn test_parse_short_short_uint() {
        assert_eq!(parse_short_short_uint(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_uint(&[255]), IResult::Done(EMPTY, 255));
    }

    #[test]
    fn test_parse_short_short_int() {
        assert_eq!(parse_short_short_int(&[0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_short_int(&[255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_short_uint() {
        assert_eq!(parse_short_uint(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_uint(&[255, 255]), IResult::Done(EMPTY, 65535));
    }

    #[test]
    fn test_parse_short_int() {
        assert_eq!(parse_short_int(&[0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_short_int(&[255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_uint() {
        assert_eq!(parse_long_uint(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_uint(&[255, 255, 255, 255]), IResult::Done(EMPTY, 4294967295));
    }

    #[test]
    fn test_parse_long_int() {
        assert_eq!(parse_long_int(&[0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_int(&[255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_long_long_uint() {
        assert_eq!(parse_long_long_uint(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_uint(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_long_long_int() {
        assert_eq!(parse_long_long_int(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_long_long_int(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, -1));
    }

    #[test]
    fn test_parse_float() {
        assert_eq!(parse_float(&[0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_float(&[42, 42, 42, 42]), IResult::Done(EMPTY, 0.00000000000015113662));
    }

    #[test]
    fn test_parse_double() {
        assert_eq!(parse_double(&[0,  0,  0,  0,  0,  0,  0,  0]),  IResult::Done(EMPTY, 0.));
        assert_eq!(parse_double(&[42, 42, 42, 42, 42, 42, 42, 42]), IResult::Done(EMPTY, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014260258159703532));
    }

    #[test]
    fn test_parse_decimal_value() {
        assert_eq!(parse_decimal_value(&[0,   0,   0,   0,   0]),   IResult::Done(EMPTY, DecimalValue { scale: 0,   value: 0          }));
        assert_eq!(parse_decimal_value(&[255, 255, 255, 255, 255]), IResult::Done(EMPTY, DecimalValue { scale: 255, value: 4294967295 }));
    }

    #[test]
    fn test_parse_short_string() {
        assert_eq!(parse_short_string(&[0]),                     IResult::Done(EMPTY, ShortString::new()));
        assert_eq!(parse_short_string(&[4, 116, 101, 115, 116]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_long_string() {
        assert_eq!(parse_long_string(&[0, 0, 0, 0]),                     IResult::Done(EMPTY, LongString::new()));
        assert_eq!(parse_long_string(&[0, 0, 0, 4, 116, 101, 115, 116]), IResult::Done(EMPTY, "test".to_string()));
    }

    #[test]
    fn test_parse_field_array() {
        assert_eq!(parse_field_array(&[0, 0, 0, 0]), IResult::Done(EMPTY, FieldArray::new()));
    }

    #[test]
    fn test_parse_timestamp() {
        assert_eq!(parse_timestamp(&[0,   0,   0,   0,   0,   0,   0,   0]),   IResult::Done(EMPTY, 0));
        assert_eq!(parse_timestamp(&[255, 255, 255, 255, 255, 255, 255, 255]), IResult::Done(EMPTY, 18446744073709551615));
    }

    #[test]
    fn test_parse_field_table() {
        assert_eq!(parse_field_table(&[0, 0, 0, 0]), IResult::Done(EMPTY, FieldTable::new()));
    }
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::IntoUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install")
                .alias("vers")
                .value_name("VERSION")
                .requires("crate"),
        )
        .arg(
            opt("git", "Git URL to install the specified crate from")
                .value_name("URL")
                .conflicts_with_all(&["path", "registry"]),
        )
        .arg(
            opt("branch", "Branch to use when installing from git")
                .value_name("BRANCH")
                .requires("git"),
        )
        .arg(
            opt("tag", "Tag to use when installing from git")
                .value_name("TAG")
                .requires("git"),
        )
        .arg(
            opt("rev", "Specific commit to use when installing from git")
                .value_name("SHA")
                .requires("git"),
        )
        .arg(
            opt("path", "Filesystem path to local crate to install")
                .value_name("PATH")
                .conflicts_with_all(&["git", "registry"]),
        )
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg(opt(
            "no-track",
            "Do not save tracking information (unstable)",
        ))
        .arg_features()
        .arg_profile("Install artifacts with from the specified profile")
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(
            opt("registry", "Registry to use")
                .value_name("REGISTRY")
                .requires("crate")
                .conflicts_with_all(&["git", "path"]),
        )
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only
packages which have executable [[bin]] or [[example]] targets can be
installed, and all executables are installed into the installation root's
`bin` folder. The installation root is determined, in order of precedence, by
`--root`, `$CARGO_INSTALL_ROOT`, the `install.root` configuration key, and
finally the home directory (which is either `$CARGO_HOME` if set or
`$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git`, `--path`, and `--registry` flags can
change this source. If the source contains more than one package (such as
crates.io or a git repository with multiple crates) the `<crate>` argument is
required to indicate which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will install the crate in the
current directory. This behaviour is deprecated, and it no longer works in the
Rust 2018 edition. Use the more explicit `install --path .` instead.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    if let Some(path) = args.value_of_path("path", config) {
        config.reload_rooted_at(path)?;
    } else {
        config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
    }

    let workspace = args.workspace(config).ok();
    let mut compile_opts = args.compile_options(
        config,
        CompileMode::Build,
        workspace.as_ref(),
        ProfileChecking::Checked,
    )?;

    compile_opts.build_config.profile_kind =
        args.get_profile_kind(config, ProfileKind::Release, ProfileChecking::Checked)?;

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.into_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("no-track") && !config.cli_unstable().install_upgrade {
        return Err(failure::format_err!(
            "`--no-track` flag is unstable, pass `-Z install-upgrade` to enable it"
        )
        .into());
    };

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
            args.is_present("no-track"),
        )?;
    }
    Ok(())
}
<commit_msg>Fix typo in `cargo install --profile` help<commit_after>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::IntoUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install")
                .alias("vers")
                .value_name("VERSION")
                .requires("crate"),
        )
        .arg(
            opt("git", "Git URL to install the specified crate from")
                .value_name("URL")
                .conflicts_with_all(&["path", "registry"]),
        )
        .arg(
            opt("branch", "Branch to use when installing from git")
                .value_name("BRANCH")
                .requires("git"),
        )
        .arg(
            opt("tag", "Tag to use when installing from git")
                .value_name("TAG")
                .requires("git"),
        )
        .arg(
            opt("rev", "Specific commit to use when installing from git")
                .value_name("SHA")
                .requires("git"),
        )
        .arg(
            opt("path", "Filesystem path to local crate to install")
                .value_name("PATH")
                .conflicts_with_all(&["git", "registry"]),
        )
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg(opt(
            "no-track",
            "Do not save tracking information (unstable)",
        ))
        .arg_features()
        .arg_profile("Install artifacts with the specified profile")
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(
            opt("registry", "Registry to use")
                .value_name("REGISTRY")
                .requires("crate")
                .conflicts_with_all(&["git", "path"]),
        )
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only
packages which have executable [[bin]] or [[example]] targets can be
installed, and all executables are installed into the installation root's
`bin` folder. The installation root is determined, in order of precedence, by
`--root`, `$CARGO_INSTALL_ROOT`, the `install.root` configuration key, and
finally the home directory (which is either `$CARGO_HOME` if set or
`$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git`, `--path`, and `--registry` flags can
change this source. If the source contains more than one package (such as
crates.io or a git repository with multiple crates) the `<crate>` argument is
required to indicate which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will install the crate in the
current directory. This behaviour is deprecated, and it no longer works in the
Rust 2018 edition. Use the more explicit `install --path .` instead.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    if let Some(path) = args.value_of_path("path", config) {
        config.reload_rooted_at(path)?;
    } else {
        config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
    }

    let workspace = args.workspace(config).ok();
    let mut compile_opts = args.compile_options(
        config,
        CompileMode::Build,
        workspace.as_ref(),
        ProfileChecking::Checked,
    )?;

    compile_opts.build_config.profile_kind =
        args.get_profile_kind(config, ProfileKind::Release, ProfileChecking::Checked)?;

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.into_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("no-track") && !config.cli_unstable().install_upgrade {
        return Err(failure::format_err!(
            "`--no-track` flag is unstable, pass `-Z install-upgrade` to enable it"
        )
        .into());
    };

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
            args.is_present("no-track"),
        )?;
    }
    Ok(())
}
<|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/. */

use std::env;
use std::error;
use std::fmt;
use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::{from_utf8, Utf8Error};

extern crate tempfile;
use self::tempfile::Builder;

#[derive(Debug)]
/// Possible errors that can occur during `rustc --pretty=expanded`.
pub enum Error {
    /// Error during creation of temporary directory
    Io(io::Error),
    /// Output of `cargo metadata` was not valid utf8
    Utf8(Utf8Error),
    /// Error during execution of `cargo rustc --pretty=expanded`
    Compile(String),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}
impl From<Utf8Error> for Error {
    fn from(err: Utf8Error) -> Self {
        Error::Utf8(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(ref err) => err.fmt(f),
            Error::Utf8(ref err) => err.fmt(f),
            Error::Compile(ref err) => write!(f, "{}", err),
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::Io(ref err) => Some(err),
            Error::Utf8(ref err) => Some(err),
            Error::Compile(..) => None,
        }
    }
}

/// Use rustc to expand and pretty print the crate into a single file,
/// removing any macros in the process.
pub fn expand(
    manifest_path: &Path,
    crate_name: &str,
    version: &str,
    use_tempdir: bool,
    expand_all_features: bool,
    expand_default_features: bool,
    expand_features: &Option<Vec<String>>,
) -> Result<String, Error> {
    let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
    let mut cmd = Command::new(cargo);

    let mut _temp_dir = None; // drop guard
    if use_tempdir {
        _temp_dir = Some(Builder::new().prefix("cbindgen-expand").tempdir()?);
        cmd.env("CARGO_TARGET_DIR", _temp_dir.unwrap().path());
    } else if let Ok(ref path) = env::var("CARGO_EXPAND_TARGET_DIR") {
        cmd.env("CARGO_TARGET_DIR", path);
    } else if let Ok(ref path) = env::var("OUT_DIR") {
        // When cbindgen was started programatically from a build.rs file, Cargo is running and
        // locking the default target directory. In this case we need to use another directory,
        // else we would end up in a deadlock. If Cargo is running `OUT_DIR` will be set, so we
        // can use a directory relative to that.
        cmd.env("CARGO_TARGET_DIR", PathBuf::from(path).join("expanded"));
    }

    // Set this variable so that we don't call it recursively if we expand a crate that is using
    // cbindgen
    cmd.env("_CBINDGEN_IS_RUNNING", "1");

    cmd.arg("rustc");
    cmd.arg("--lib");
    cmd.arg("--manifest-path");
    cmd.arg(manifest_path);
    if let Some(features) = expand_features {
        cmd.arg("--features");
        let mut features_str = String::new();
        for (index, feature) in features.iter().enumerate() {
            if index != 0 {
                features_str.push_str(" ");
            }
            features_str.push_str(feature);
        }
        cmd.arg(features_str);
    }
    if expand_all_features {
        cmd.arg("--all-features");
    }
    if !expand_default_features {
        cmd.arg("--no-default-features");
    }
    cmd.arg("-p");
    cmd.arg(&format!("{}:{}", crate_name, version));
    cmd.arg("--");
    cmd.arg("-Z");
    cmd.arg("unstable-options");
    cmd.arg("--pretty=expanded");
    let output = cmd.output()?;

    let src = from_utf8(&output.stdout)?.to_owned();
    let error = from_utf8(&output.stderr)?.to_owned();

    if src.is_empty() {
        Err(Error::Compile(error))
    } else {
        Ok(src)
    }
}
<commit_msg>Enable verbose logging as well as echo the command line on expansion.<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/. */

use std::env;
use std::error;
use std::fmt;
use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::{from_utf8, Utf8Error};

extern crate tempfile;
use self::tempfile::Builder;

#[derive(Debug)]
/// Possible errors that can occur during `rustc --pretty=expanded`.
pub enum Error {
    /// Error during creation of temporary directory
    Io(io::Error),
    /// Output of `cargo metadata` was not valid utf8
    Utf8(Utf8Error),
    /// Error during execution of `cargo rustc --pretty=expanded`
    Compile(String),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}
impl From<Utf8Error> for Error {
    fn from(err: Utf8Error) -> Self {
        Error::Utf8(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(ref err) => err.fmt(f),
            Error::Utf8(ref err) => err.fmt(f),
            Error::Compile(ref err) => write!(f, "{}", err),
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::Io(ref err) => Some(err),
            Error::Utf8(ref err) => Some(err),
            Error::Compile(..) => None,
        }
    }
}

/// Use rustc to expand and pretty print the crate into a single file,
/// removing any macros in the process.
pub fn expand(
    manifest_path: &Path,
    crate_name: &str,
    version: &str,
    use_tempdir: bool,
    expand_all_features: bool,
    expand_default_features: bool,
    expand_features: &Option<Vec<String>>,
) -> Result<String, Error> {
    let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
    let mut cmd = Command::new(cargo);

    let mut _temp_dir = None; // drop guard
    if use_tempdir {
        _temp_dir = Some(Builder::new().prefix("cbindgen-expand").tempdir()?);
        cmd.env("CARGO_TARGET_DIR", _temp_dir.unwrap().path());
    } else if let Ok(ref path) = env::var("CARGO_EXPAND_TARGET_DIR") {
        cmd.env("CARGO_TARGET_DIR", path);
    } else if let Ok(ref path) = env::var("OUT_DIR") {
        // When cbindgen was started programatically from a build.rs file, Cargo is running and
        // locking the default target directory. In this case we need to use another directory,
        // else we would end up in a deadlock. If Cargo is running `OUT_DIR` will be set, so we
        // can use a directory relative to that.
        cmd.env("CARGO_TARGET_DIR", PathBuf::from(path).join("expanded"));
    }

    // Set this variable so that we don't call it recursively if we expand a crate that is using
    // cbindgen
    cmd.env("_CBINDGEN_IS_RUNNING", "1");

    cmd.arg("rustc");
    cmd.arg("--lib");
    cmd.arg("--manifest-path");
    cmd.arg(manifest_path);
    if let Some(features) = expand_features {
        cmd.arg("--features");
        let mut features_str = String::new();
        for (index, feature) in features.iter().enumerate() {
            if index != 0 {
                features_str.push_str(" ");
            }
            features_str.push_str(feature);
        }
        cmd.arg(features_str);
    }
    if expand_all_features {
        cmd.arg("--all-features");
    }
    if !expand_default_features {
        cmd.arg("--no-default-features");
    }
    cmd.arg("-p");
    cmd.arg(&format!("{}:{}", crate_name, version));
    cmd.arg("--verbose");
    cmd.arg("--");
    cmd.arg("-Z");
    cmd.arg("unstable-options");
    cmd.arg("--pretty=expanded");
    info!("Command: {:?}", cmd);
    let output = cmd.output()?;

    let src = from_utf8(&output.stdout)?.to_owned();
    let error = from_utf8(&output.stderr)?.to_owned();

    if src.is_empty() {
        Err(Error::Compile(error))
    } else {
        Ok(src)
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate toml;

use self::chrono::*;
use constants::*;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = WORKING_DIR_NAME;
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let path_to_config = path_to_dir.clone().join(CONFIG_FILE_NAME);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let path_to_ignore = path_to_dir.clone().join(IGNORE_FILE_NAME);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut f) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match f.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn walk_dir<P: AsRef<Path>>(path: P) -> BTreeSet<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter(|de| de.is_ok())
            .flat_map(|de| {
                let path = de.unwrap().path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter(|f| f.is_ok())
        .map(|f| f.unwrap())
        .collect::<BTreeSet<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with("."))
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    let now           = Local::now();
    let trash_name    = format!("trash_{}", now.format("%Y-%m-%d"));
    let path_to_trash = Path::new(WORKING_DIR_NAME).join(trash_name);
    if !(path_to_trash.exists() && path_to_trash.is_dir()) {
        match fs::create_dir(path_to_trash) {
            Ok(_)    => {},
            Err(why) => panic!("{:?}", why),
        }
    }

    println!("Sweep ...");

    let ignore = read_ignore_file();

    let target_files = walk_dir(".")
        .difference(&ignore)
        .cloned()
        .collect::<Vec<String>>();

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

fn read_ignore_file() -> BTreeSet<String> {
    let ignore_file = Path::new(WORKING_DIR_NAME).join(IGNORE_FILE_NAME);
    let mut f       = match File::open(ignore_file) {
        Ok(f)    => f,
        Err(why) => panic!("{:?}", why),
    };
    let mut contents = String::new();
    match f.read_to_string(&mut contents) {
        Ok(_)    => {},
        Err(why) => panic!("{:?}", why),
    }
    contents
        .lines()
        .map(|l| l.trim().to_string())
        .collect::<BTreeSet<String>>()
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    match fs::remove_dir_all(WORKING_DIR_NAME) {
        Ok(_)    => println!("  OK: Removed \"{}\" directory.", WORKING_DIR_NAME),
        Err(why) => panic!("{:?}", why),
    }
}
<commit_msg>Remove useless "extern"<commit_after>extern crate chrono;

use self::chrono::*;
use constants::*;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = WORKING_DIR_NAME;
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let path_to_config = path_to_dir.clone().join(CONFIG_FILE_NAME);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let path_to_ignore = path_to_dir.clone().join(IGNORE_FILE_NAME);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut f) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match f.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn walk_dir<P: AsRef<Path>>(path: P) -> BTreeSet<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter(|de| de.is_ok())
            .flat_map(|de| {
                let path = de.unwrap().path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter(|f| f.is_ok())
        .map(|f| f.unwrap())
        .collect::<BTreeSet<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with("."))
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    let now           = Local::now();
    let trash_name    = format!("trash_{}", now.format("%Y-%m-%d"));
    let path_to_trash = Path::new(WORKING_DIR_NAME).join(trash_name);
    if !(path_to_trash.exists() && path_to_trash.is_dir()) {
        match fs::create_dir(path_to_trash) {
            Ok(_)    => {},
            Err(why) => panic!("{:?}", why),
        }
    }

    println!("Sweep ...");

    let ignore = read_ignore_file();

    let target_files = walk_dir(".")
        .difference(&ignore)
        .cloned()
        .collect::<Vec<String>>();

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

fn read_ignore_file() -> BTreeSet<String> {
    let ignore_file = Path::new(WORKING_DIR_NAME).join(IGNORE_FILE_NAME);
    let mut f       = match File::open(ignore_file) {
        Ok(f)    => f,
        Err(why) => panic!("{:?}", why),
    };
    let mut contents = String::new();
    match f.read_to_string(&mut contents) {
        Ok(_)    => {},
        Err(why) => panic!("{:?}", why),
    }
    contents
        .lines()
        .map(|l| l.trim().to_string())
        .collect::<BTreeSet<String>>()
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    match fs::remove_dir_all(WORKING_DIR_NAME) {
        Ok(_)    => println!("  OK: Removed \"{}\" directory.", WORKING_DIR_NAME),
        Err(why) => panic!("{:?}", why),
    }
}
<|endoftext|>