<commit_before>extern crate base64;
extern crate crypto;
extern crate hyper;
extern crate hyper_native_tls;
extern crate rand;
extern crate serde_json;
extern crate time;
extern crate url;

use std::io::Read;
use std::collections::{HashMap, BTreeMap};

use crypto::sha1::Sha1;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use hyper::Client;
use hyper::header::{Headers, Authorization, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use rand::Rng;
use url::Url;
use url::percent_encoding::{EncodeSet, percent_encode};

#[derive(Copy, Clone)]
struct StrictEncodeSet;

impl EncodeSet for StrictEncodeSet {
    fn contains(&self, byte: u8) -> bool {
        !((byte >= "0".as_bytes()[0] && byte <= "9".as_bytes()[0]) ||
            (byte >= "a".as_bytes()[0] && byte <= "z".as_bytes()[0]) ||
            (byte >= "A".as_bytes()[0] && byte <= "Z".as_bytes()[0]) ||
            (byte == "-".as_bytes()[0]) ||
            (byte == ".".as_bytes()[0]) ||
            (byte == "_".as_bytes()[0]) ||
            (byte == "~".as_bytes()[0])
        )
    }
}

#[derive(Clone, Debug)]
pub struct Oauth {
    pub consumer_key: Option<String>,
    pub consumer_secret: Option<String>,
    pub access_token: Option<String>,
    pub access_token_secret: Option<String>
}

impl Oauth {
    pub fn new(ck: Option<String>, cs: Option<String>, at: Option<String>, ats: Option<String>) -> Oauth {
        Oauth {
            consumer_key: ck,
            consumer_secret: cs,
            access_token: at,
            access_token_secret: ats
        }
    }

    pub fn get_request_url(&mut self) -> String {
        let (request_token, request_token_secret) = get_request_token(&self).unwrap();
        let mut request_url = Url::parse("http://api.twitter.com/oauth/authorize").unwrap();
        request_url.query_pairs_mut().append_pair("oauth_token", &request_token);
        request_url.query_pairs_mut().append_pair("oauth_token_secret", &request_token_secret);

        self.access_token = Some(request_token);
        self.access_token_secret = Some(request_token_secret);
        request_url.to_string()
    }

    pub fn set_access_token(&mut self, verifier: &str) {
        let url = "https://api.twitter.com/oauth/access_token";

        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut params: BTreeMap<&str, &str> = BTreeMap::new();
        params.insert("oauth_token", &token);
        params.insert("oauth_verifier", verifier);
        let (header, _) = build_request(&self, "POST", url, params, &token_secret);

        let (oauth_token, oauth_token_secret) = get_oauth_token(get_token(url, &header)).unwrap();
        self.access_token = Some(oauth_token);
        self.access_token_secret = Some(oauth_token_secret);
    }

    pub fn post(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, body) = build_request(&self, "POST", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        headers.set(ContentType(Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, vec![(Attr::Charset, Value::Utf8)])));
        let client = Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.post(&url)
            .headers(headers)
            .body(&body)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }

    pub fn get(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, _) = build_request(&self, "GET", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        let client = Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.get(&url)
            .headers(headers)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }
}

fn encode(s: &str) -> String {
    percent_encode(s.as_bytes(), StrictEncodeSet).collect::<String>()
}

fn build_request(
    oauth: &Oauth,
    method: &str,
    url: &str,
    append_params: BTreeMap<&str, &str>,
    oauth_token_secret: &str
) -> (String, String) {
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();
    let now_time = time::now().to_timespec().sec.to_string();
    let key = oauth.consumer_key.clone().unwrap();
    let key_secret = oauth.consumer_secret.clone().unwrap();

    let mut params: BTreeMap<&str, &str> = BTreeMap::new();
    params.insert("oauth_consumer_key", &key);
    params.insert("oauth_nonce", &nonce);
    params.insert("oauth_signature_method", "HMAC-SHA1");
    params.insert("oauth_timestamp", &now_time);
    params.insert("oauth_version", "1.0a");

    for (k, v) in append_params {
        params.insert(k, v);
    }

    let param = params
        .iter()
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&");

    let oauth_signature = {
        let signature_param = format!("{}&{}&{}", encode(method.to_uppercase().as_str()), encode(url), encode(&param));
        let key = format!("{}&{}", encode(&key_secret), encode(oauth_token_secret));
        let mut hmac = Hmac::new(Sha1::new(), key.as_bytes());
        hmac.input(signature_param.as_bytes());
        base64::encode(hmac.result().code())
    };

    let mut values = params;
    values.insert("oauth_signature", &oauth_signature);

    (build_header(&values), build_body(&values))
}

fn build_header(params: &BTreeMap<&str, &str>) -> String {
    let header = params
        .iter()
        .filter(|&(k, _)| k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}=\"{}\"", k, encode(v)))
        .collect::<Vec<_>>()
        .join(", ");
    format!("OAuth {}", header)
}

fn build_body(params: &BTreeMap<&str, &str>) -> String {
    params
        .iter()
        .filter(|&(k, _)| !k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&")
}

fn get_token(url: &str, header_value: &str) -> String {
    let client = Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
    let mut headers = Headers::new();
    headers.set(Authorization(header_value.to_string()));
    let mut res = client
        .post(url)
        .headers(headers)
        .send()
        .unwrap();

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    body
}

fn get_request_token(oauth: &Oauth) -> Result<(String, String), String> {
    let url = "https://api.twitter.com/oauth/request_token";

    let mut params = BTreeMap::new();
    params.insert("oauth_callback", "oob");
    let (header, _) = build_request(&oauth, "POST", url, params, "");

    get_oauth_token(get_token(url, &header))
}

fn get_oauth_token(body: String) -> Result<(String, String), String> {
    let query = match serde_json::from_str::<serde_json::Value>(&body) {
        Ok(json) => return Err(json["errors"][0]["message"].to_string()),
        Err(..) => body,
    };

    let mut parsed_url = Url::parse("http://example.com").unwrap();
    parsed_url.set_query(Some(&query));
    let hash_query: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();

    Ok((hash_query["oauth_token"].to_string(), hash_query["oauth_token_secret"].to_string()))
}
<commit_msg>†Struct名を変更<commit_after>extern crate base64;
extern crate crypto;
extern crate hyper;
extern crate hyper_native_tls;
extern crate rand;
extern crate serde_json;
extern crate time;
extern crate url;

use std::io::Read;
use std::collections::{HashMap, BTreeMap};

use crypto::sha1::Sha1;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use hyper::header::{Headers, Authorization, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use rand::Rng;
use url::Url;
use url::percent_encoding::{EncodeSet, percent_encode};

#[derive(Copy, Clone)]
struct StrictEncodeSet;

impl EncodeSet for StrictEncodeSet {
    fn contains(&self, byte: u8) -> bool {
        !((byte >= "0".as_bytes()[0] && byte <= "9".as_bytes()[0]) ||
            (byte >= "a".as_bytes()[0] && byte <= "z".as_bytes()[0]) ||
            (byte >= "A".as_bytes()[0] && byte <= "Z".as_bytes()[0]) ||
            (byte == "-".as_bytes()[0]) ||
            (byte == ".".as_bytes()[0]) ||
            (byte == "_".as_bytes()[0]) ||
            (byte == "~".as_bytes()[0])
        )
    }
}

#[derive(Clone, Debug)]
pub struct Client {
    pub consumer_key: Option<String>,
    pub consumer_secret: Option<String>,
    pub access_token: Option<String>,
    pub access_token_secret: Option<String>
}

impl Client {
    pub fn new(ck: Option<String>, cs: Option<String>, at: Option<String>, ats: Option<String>) -> Client {
        Client {
            consumer_key: ck,
            consumer_secret: cs,
            access_token: at,
            access_token_secret: ats
        }
    }

    pub fn get_request_url(&mut self) -> String {
        let (request_token, request_token_secret) = get_request_token(&self).unwrap();
        let mut request_url = Url::parse("http://api.twitter.com/oauth/authorize").unwrap();
        request_url.query_pairs_mut().append_pair("oauth_token", &request_token);
        request_url.query_pairs_mut().append_pair("oauth_token_secret", &request_token_secret);

        self.access_token = Some(request_token);
        self.access_token_secret = Some(request_token_secret);
        request_url.to_string()
    }

    pub fn set_access_token(&mut self, verifier: &str) {
        let url = "https://api.twitter.com/oauth/access_token";

        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut params: BTreeMap<&str, &str> = BTreeMap::new();
        params.insert("oauth_token", &token);
        params.insert("oauth_verifier", verifier);
        let (header, _) = build_request(&self, "POST", url, params, &token_secret);

        let (oauth_token, oauth_token_secret) = get_oauth_token(get_token(url, &header)).unwrap();
        self.access_token = Some(oauth_token);
        self.access_token_secret = Some(oauth_token_secret);
    }

    pub fn post(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, body) = build_request(&self, "POST", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        headers.set(ContentType(Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, vec![(Attr::Charset, Value::Utf8)])));
        let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.post(&url)
            .headers(headers)
            .body(&body)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }

    pub fn get(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, _) = build_request(&self, "GET", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.get(&url)
            .headers(headers)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }
}

fn encode(s: &str) -> String {
    percent_encode(s.as_bytes(), StrictEncodeSet).collect::<String>()
}

fn build_request(
    oauth: &Client,
    method: &str,
    url: &str,
    append_params: BTreeMap<&str, &str>,
    oauth_token_secret: &str
) -> (String, String) {
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();
    let now_time = time::now().to_timespec().sec.to_string();
    let key = oauth.consumer_key.clone().unwrap();
    let key_secret = oauth.consumer_secret.clone().unwrap();

    let mut params: BTreeMap<&str, &str> = BTreeMap::new();
    params.insert("oauth_consumer_key", &key);
    params.insert("oauth_nonce", &nonce);
    params.insert("oauth_signature_method", "HMAC-SHA1");
    params.insert("oauth_timestamp", &now_time);
    params.insert("oauth_version", "1.0a");

    for (k, v) in append_params {
        params.insert(k, v);
    }

    let param = params
        .iter()
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&");

    let oauth_signature = {
        let signature_param = format!("{}&{}&{}", encode(method.to_uppercase().as_str()), encode(url), encode(&param));
        let key = format!("{}&{}", encode(&key_secret), encode(oauth_token_secret));
        let mut hmac = Hmac::new(Sha1::new(), key.as_bytes());
        hmac.input(signature_param.as_bytes());
        base64::encode(hmac.result().code())
    };

    let mut values = params;
    values.insert("oauth_signature", &oauth_signature);

    (build_header(&values), build_body(&values))
}

fn build_header(params: &BTreeMap<&str, &str>) -> String {
    let header = params
        .iter()
        .filter(|&(k, _)| k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}=\"{}\"", k, encode(v)))
        .collect::<Vec<_>>()
        .join(", ");
    format!("OAuth {}", header)
}

fn build_body(params: &BTreeMap<&str, &str>) -> String {
    params
        .iter()
        .filter(|&(k, _)| !k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&")
}

fn get_token(url: &str, header_value: &str) -> String {
    let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
    let mut headers = Headers::new();
    headers.set(Authorization(header_value.to_string()));
    let mut res = client
        .post(url)
        .headers(headers)
        .send()
        .unwrap();

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    body
}

fn get_request_token(oauth: &Client) -> Result<(String, String), String> {
    let url = "https://api.twitter.com/oauth/request_token";

    let mut params = BTreeMap::new();
    params.insert("oauth_callback", "oob");
    let (header, _) = build_request(&oauth, "POST", url, params, "");

    get_oauth_token(get_token(url, &header))
}

fn get_oauth_token(body: String) -> Result<(String, String), String> {
    let query = match serde_json::from_str::<serde_json::Value>(&body) {
        Ok(json) => return Err(json["errors"][0]["message"].to_string()),
        Err(..) => body,
    };

    let mut parsed_url = Url::parse("http://example.com").unwrap();
    parsed_url.set_query(Some(&query));
    let hash_query: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();

    Ok((hash_query["oauth_token"].to_string(), hash_query["oauth_token_secret"].to_string()))
}
<|endoftext|>


<commit_before>/*!

This crate provides some macros for quickly parsing values out of text.  Roughly speaking, it does the inverse of the `print!`/`format!` macros; or, in other words, a similar job to `scanf` from C.

The macros of interest are:

* [`readln!`](macro.readln!.html) - reads and scans a line from standard input.
* [`try_readln!`](macro.try_readln!.html) - like `readln!`, except it returns a `Result` instead of panicking.
* [`scan!`](macro.scan!.html) - scans the provided string.

If you are interested in implementing support for your own types, see the [`ScanFromStr`](scanner/trait.ScanFromStr.html) trait.

The available abstract scanners can be found in the [`scanner`](scanner/index.html) module.

**Links**

* [Latest Release](https://crates.io/crates/scan-rules/)
* [Latest Docs](https://danielkeep.github.io/rust-scan-rules/doc/scan_rules/index.html)
* [Repository](https://github.com/DanielKeep/rust-scan-rules)

## Features

The following optional features are available:

* `arrays-32`: implement scanning for arrays of up to 32 elements.  The default is up to 8 elements.

* `tuples-16`: implement scanning for tuples of up to 16 elements.  The default is up to 4 elements.

## Quick Examples

Here is a simple CLI program that asks the user their name and age.  You can run this using `cargo run --example ask_age`.

```ignore
#[macro_use] extern crate scan_rules;

use scan_rules::scanner::Word;

fn main() {
    print!("What's your name? ");
    let name: String = readln! { (let name: Word<String>) => name };
    //                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ rule
    //                                                       ^~~^ body
    //                           ^~~~~~~~~~~~~~~~~~~~~~~^ pattern
    //                            ^~~~~~~~~~~~~~~~~~~~~^ variable binding

    print!("Hi, {}.  How old are you? ", name);
    readln! {
        (let age) => {
    //   ^~~~~~^ implicitly typed variable binding
            let age: i32 = age;
            println!("{} years old, huh?  Neat.", age);
        },
        (..other) => println!("`{}` doesn't *look* like a number...", other),
    //   ^~~~~~^ bind to any input "left over"
    }
}
```

This example shows how to parse one of several different syntaxes.  You can run this using `cargo run --example scan_data`.

```ignore
#[macro_use] extern crate scan_rules;

use std::collections::BTreeSet;

// `Word` is an "abstract" scanner; rather than scanning itself, it scans some
// *other* type using custom rules.  In this case, it scans a word into a
// string slice.  You can use `Word<String>` to get an owned string.
use scan_rules::scanner::Word;

#[derive(Debug)]
enum Data {
    Vector(i32, i32, i32),
    Truthy(bool),
    Words(Vec<String>),
    Lucky(BTreeSet<i32>),
    Other(String),
}

fn main() {
    print!("Enter some data: ");
    let data = readln! {
        ("<", let x, ",", let y, ",", let z, ">") => Data::Vector(x, y, z),
    //      ^ pattern terms are comma-separated
    //   ^~^ literal text match

        // Rules are tried top-to-bottom, stopping as soon as one matches.
        (let b) => Data::Truthy(b),
        ("yes") => Data::Truthy(true),
        ("no") => Data::Truthy(false),

        ("words:", [ let words: Word<String> ],+) => Data::Words(words),
    //             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~^ repetition pattern
    //                                         ^ one or more matches
    //                                        ^ matches must be comma-separated

        ("lucky numbers:", [ let ns: i32 ]*: BTreeSet<_>) => Data::Lucky(ns),
    //          collect into specific type ^~~~~~~~~~~~^
    //                                    ^ zero or more (you might be unlucky!)
    //                                      (no separator this time)

        // Rather than scanning a sequence of values and collecting them into
        // a `BTreeSet`, we can instead scan the `BTreeSet` *directly*.  This
        // scans the syntax `BTreeSet` uses when printed using `{:?}`:
        // `{1, 5, 13, ...}`.
        ("lucky numbers:", let ns) => Data::Lucky(ns),

        (..other) => Data::Other(String::from(other))
    };
    println!("data: {:?}", data);
}
```

## Pattern Syntax

A scanning pattern is made up of one or more pattern terms, separated by commas.  The following terms are supported:

* *strings* - any expression that evaluates to a string will be used as a literal match on the input.  Exactly *how* this match is done depends on the kind of input, but the default is to do a case-sensitive match of whole words, individual non-letter characters, and to ignore all whitespace.

  *E.g.* `"Two words"`, `"..."` (counts as three "words"), `&format!("{} {}", "Two", "words")`.

* `let` *name* \[ `:` *type* ] - scans a value out of the input text, and binds it to *name*.  If *type* is omitted, it will be inferred.

  *E.g.* `let x`, `let n: i32`, `let words: Vec<_>`, `let _: &str` (scans and discards a value).

* `..` *name* - binds the remaining, unscanned input as a string to *name*.  This can *only* appear as the final term in a top-level pattern.

* `[` *pattern* `]` \[ *(nothing)* | `,` | `(` *seperator pattern* `)` ] ( `?` | `*` | `+` | `{` *range* `}` ) \[ ":" *collection type* ] - scans *pattern* repeatedly.

  The first (mandatory) part of the term specifies the *pattern* that should be repeatedly scanned.

  The second (optional) part of the term controls if (and what) repeats are separated by.  `,` is provided as a short-cut to an obvious common case; it is equivalent to writing `(",")`.  Otherwise, you may write any arbitrary *separator pattern* as the separator, including variable bindings and more repetitions.

  The third (mandatory) part of the term specifies how many times *pattern* should be scanned.  The available options are:

  * `?` - match zero or one times.
  * `*` - match zero or more times.
  * `+` - match one or more times.
  * `{n}` - match exactly *n* times.
  * `{a,}` - match at least *a* times.
  * `{,b}` - match at most *b* times.
  * `{a, b}` - match at least *a* times, and at most *b* times.

  The fourth (optional) part of the term specifies what type of collection scanned values should be added to.  Note that the type specified here applies to *all* values captured by this repetition.  As such, you typically want to use a partially inferred type such as `BTreeSet<_>`.  If omitted, it defaults to `Vec<_>`.

  *E.g.* `[ let nums: i32 ],+`, `[ "pretty" ]*, "please"`.

## Things What Need Mentioning

* *Rule* syntax.
* Scanners and things like `Word` being abstract.
* Cursor(s).
* More examples.
* `#![recursion_limit]`

*/
#![forbid(missing_docs)]
#![recursion_limit="128"]
#[macro_use] extern crate lazy_static;
extern crate itertools;
extern crate regex;
extern crate strcursor;

#[macro_use] mod macros;

pub use error::{ScanError, ScanErrorKind};

mod error;
pub mod input;
pub mod scanner;

/**
Remove a single trailing line terminator from `s`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn strip_line_term(s: &str) -> &str {
    if s.ends_with("\r\n") {
        &s[0..s.len()-2]
    } else if s.ends_with("\n") {
        &s[0..s.len()-1]
    } else if s.ends_with("\r") {
        &s[0..s.len()-1]
    } else {
        s
    }
}

/**
Compute the offset of `b`, which must be a subslice of `a`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn subslice_offset(a: &str, b: &str) -> Option<usize> {
    use scanner::util::StrUtil;
    a.subslice_offset(b)
}
<commit_msg>More docs.<commit_after>/*!

This crate provides some macros for quickly parsing values out of text.  Roughly speaking, it does the inverse of the `print!`/`format!` macros; or, in other words, a similar job to `scanf` from C.

The macros of interest are:

* [`readln!`](macro.readln!.html) - reads and scans a line from standard input.
* [`try_readln!`](macro.try_readln!.html) - like `readln!`, except it returns a `Result` instead of panicking.
* [`scan!`](macro.scan!.html) - scans the provided string.

If you are interested in implementing support for your own types, see the [`ScanFromStr`](scanner/trait.ScanFromStr.html) trait.

The available abstract scanners can be found in the [`scanner`](scanner/index.html) module.

**Links**

* [Latest Release](https://crates.io/crates/scan-rules/)
* [Latest Docs](https://danielkeep.github.io/rust-scan-rules/doc/scan_rules/index.html)
* [Repository](https://github.com/DanielKeep/rust-scan-rules)

## Features

The following optional features are available:

* `arrays-32`: implement scanning for arrays of up to 32 elements.  The default is up to 8 elements.

* `tuples-16`: implement scanning for tuples of up to 16 elements.  The default is up to 4 elements.

## Important Notes

* There are no default scanners for `&str` or `String`; if you want a string, you should pick an appropriate abstract scanner from the [`scanner`](scanner/index.html) module.

* The macros in this crate are extremely complex.  Moderately complex usage can exhaust the standard macro recursion limit.  If this happens, you can raise the limit (from its default of 64) by adding the following attribute to your crate's root module:

  `#![recursion_limit="128"]`

## Quick Examples

Here is a simple CLI program that asks the user their name and age.  You can run this using `cargo run --example ask_age`.

```ignore
#[macro_use] extern crate scan_rules;

use scan_rules::scanner::Word;

fn main() {
    print!("What's your name? ");
    let name: String = readln! { (let name: Word<String>) => name };
    //                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ rule
    //                                                       ^~~^ body
    //                           ^~~~~~~~~~~~~~~~~~~~~~~^ pattern
    //                            ^~~~~~~~~~~~~~~~~~~~~^ variable binding

    print!("Hi, {}.  How old are you? ", name);
    readln! {
        (let age) => {
    //   ^~~~~~^ implicitly typed variable binding
            let age: i32 = age;
            println!("{} years old, huh?  Neat.", age);
        },
        (..other) => println!("`{}` doesn't *look* like a number...", other),
    //   ^~~~~~^ bind to any input "left over"
    }
}
```

This example shows how to parse one of several different syntaxes.  You can run this using `cargo run --example scan_data`.

```ignore
#[macro_use] extern crate scan_rules;

use std::collections::BTreeSet;

// `Word` is an "abstract" scanner; rather than scanning itself, it scans some
// *other* type using custom rules.  In this case, it scans a word into a
// string slice.  You can use `Word<String>` to get an owned string.
use scan_rules::scanner::Word;

#[derive(Debug)]
enum Data {
    Vector(i32, i32, i32),
    Truthy(bool),
    Words(Vec<String>),
    Lucky(BTreeSet<i32>),
    Other(String),
}

fn main() {
    print!("Enter some data: ");
    let data = readln! {
        ("<", let x, ",", let y, ",", let z, ">") => Data::Vector(x, y, z),
    //      ^ pattern terms are comma-separated
    //   ^~^ literal text match

        // Rules are tried top-to-bottom, stopping as soon as one matches.
        (let b) => Data::Truthy(b),
        ("yes") => Data::Truthy(true),
        ("no") => Data::Truthy(false),

        ("words:", [ let words: Word<String> ],+) => Data::Words(words),
    //             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~^ repetition pattern
    //                                         ^ one or more matches
    //                                        ^ matches must be comma-separated

        ("lucky numbers:", [ let ns: i32 ]*: BTreeSet<_>) => Data::Lucky(ns),
    //          collect into specific type ^~~~~~~~~~~~^
    //                                    ^ zero or more (you might be unlucky!)
    //                                      (no separator this time)

        // Rather than scanning a sequence of values and collecting them into
        // a `BTreeSet`, we can instead scan the `BTreeSet` *directly*.  This
        // scans the syntax `BTreeSet` uses when printed using `{:?}`:
        // `{1, 5, 13, ...}`.
        ("lucky numbers:", let ns) => Data::Lucky(ns),

        (..other) => Data::Other(String::from(other))
    };
    println!("data: {:?}", data);
}
```

## Rule Syntax

Scanning rules are written as one or more arms like so:

```ignore
scan! { input_expression;
    ( pattern ) => body,
    ( pattern ) => body,
    ...
    ( pattern ) => body,
}
```

Note that the trailing comma on the last rule is optional.

Rules are checked top-to-bottom, stopping at the first that matches.

Patterns (explained under ["Pattern Syntax"](#pattern-syntax)) must be enclosed in parentheses.  If a pattern matches the provided input, the corresponding body is evaluated.

### Pattern Syntax

A scanning pattern is made up of one or more pattern terms, separated by commas.  The following terms are supported:

* *strings* - any expression that evaluates to a string will be used as a literal match on the input.  Exactly *how* this match is done depends on the kind of input, but the default is to do a case-sensitive match of whole words, individual non-letter characters, and to ignore all whitespace.

  *E.g.* `"Two words"`, `"..."` (counts as three "words"), `&format!("{} {}", "Two", "words")`.

* `let` *name* \[ `:` *type* ] - scans a value out of the input text, and binds it to *name*.  If *type* is omitted, it will be inferred.

  *E.g.* `let x`, `let n: i32`, `let words: Vec<_>`, `let _: &str` (scans and discards a value).

* `..` *name* - binds the remaining, unscanned input as a string to *name*.  This can *only* appear as the final term in a top-level pattern.

* `[` *pattern* `]` \[ *(nothing)* | `,` | `(` *seperator pattern* `)` ] ( `?` | `*` | `+` | `{` *range* `}` ) \[ ":" *collection type* ] - scans *pattern* repeatedly.

  The first (mandatory) part of the term specifies the *pattern* that should be repeatedly scanned.

  The second (optional) part of the term controls if (and what) repeats are separated by.  `,` is provided as a short-cut to an obvious common case; it is equivalent to writing `(",")`.  Otherwise, you may write any arbitrary *separator pattern* as the separator, including variable bindings and more repetitions.

  The third (mandatory) part of the term specifies how many times *pattern* should be scanned.  The available options are:

  * `?` - match zero or one times.
  * `*` - match zero or more times.
  * `+` - match one or more times.
  * `{n}` - match exactly *n* times.
  * `{a,}` - match at least *a* times.
  * `{,b}` - match at most *b* times.
  * `{a, b}` - match at least *a* times, and at most *b* times.

  The fourth (optional) part of the term specifies what type of collection scanned values should be added to.  Note that the type specified here applies to *all* values captured by this repetition.  As such, you typically want to use a partially inferred type such as `BTreeSet<_>`.  If omitted, it defaults to `Vec<_>`.

  *E.g.* `[ let nums: i32 ],+`, `[ "pretty" ]*, "please"`.

*/
#![forbid(missing_docs)]
#![recursion_limit="128"]
#[macro_use] extern crate lazy_static;
extern crate itertools;
extern crate regex;
extern crate strcursor;

#[macro_use] mod macros;

pub use error::{ScanError, ScanErrorKind};

mod error;
pub mod input;
pub mod scanner;

/**
Remove a single trailing line terminator from `s`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn strip_line_term(s: &str) -> &str {
    if s.ends_with("\r\n") {
        &s[0..s.len()-2]
    } else if s.ends_with("\n") {
        &s[0..s.len()-1]
    } else if s.ends_with("\r") {
        &s[0..s.len()-1]
    } else {
        s
    }
}

/**
Compute the offset of `b`, which must be a subslice of `a`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn subslice_offset(a: &str, b: &str) -> Option<usize> {
    use scanner::util::StrUtil;
    a.subslice_offset(b)
}
<|endoftext|>


<commit_before>//! Chomp is an alternative parser combinator library for the Rust programming language. It was written as the culmination of the experiments detailed in these blog posts:
//! * [Part 1](http://m4rw3r.github.io/parser-combinator-experiments-rust/)
//! * [Part 2](http://m4rw3r.github.io/parser-combinator-experiments-errors)
//! * [Part 3](http://m4rw3r.github.io/parser-combinator-experiments-part-3)
//!
//! For its current capabilities, you will find that Chomp performs consistently as well, if not better, than optimized C parsers, while being vastly more expressive. For an example that builds a performant HTTP parser out of smaller parsers, see [http_parser.rs](examples/http_parser.rs).
//! # Example
//!
//! ```
//! use chomp::{Input, ParseResult, Error};
//! use chomp::{take_while1, token};
//!
//! let i = Input::new("martin wernstål\n".as_bytes());
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Name<'a> {
//!     first: &'a [u8],
//!     last:  &'a [u8],
//! }
//!
//! fn name(i: Input<u8>) -> ParseResult<u8, Name, Error<u8>> {
//!     take_while1(i, |c| c != b' ').bind(|i, first|
//!         token(i, b' ').bind(|i, _| // skipping this char
//!             take_while1(i, |c| c != b'\n').bind(|i, last|
//!                 i.ret(Name{
//!                     first: first,
//!                     last:  last,
//!                 }))))
//! }
//!
//! assert_eq!(name(i).unwrap(), Name{first: b"martin", last: "wernstål".as_bytes()});
//! ```
//! # Usage
//! Chomp's functionality is split between three modules.
//!* `parsers` contains the basic parsers used to parse streams of input.
//!* `combinators` contains functions which take parsers and return new ones.
//!* `internal` contains the building blocks used to make new parsers. This is advanced usage and is far more involved than using the preexisting parsers, but is sometimes unavoidable.
//!
//!    A parser is, at its simplest, a function that takes a slice of input and returns a `ParserResult<'a, I, T, E>`, where I, T, and E are the input, output, and error types, respectively. Parsers are usually parameterized over values or other parsers as well, so these appear as extra arguments in the parsing function. As an example, here is the signature of the `token` parser, which matches a particular input.
//!
//!```
//!fn token<'a, I: 'a + Copy + Eq>(i: Input<'a, I>, t: I) -> SimpleResult<'a, I, I> {...}
//!```
//!
//!    Notice that the first argument is an `Input<'a, I>`, and the second argument is some `I`. `Input<'a,I>` is just a datatype over the current state of the parser and a slice of input `I`, and prevents the parser writer from accidentally mutating the state of the parser. Later, when we introduce the `parse!` macro, we will see that using a parser in this macro just means supplying all of the arguments but the input, as so:
//!```
//!token(b'T');
//!```
//!Note that you cannot do this outside of the `parse!` macro.
//!`SimpleResult<'a, I, T>` is a convenience type alias over Result<'a, I, T, Error<u8>>, and `Error<I>` is just a convenient "default" error type that will satisfy most users. For more sophisticated usage, one can always write a custom error type.
//!
//!    A very useful parser is the `satisfy` parser:
//!```
//!fn satisfy<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, I>
//!    where F: FnOnce(I) -> bool { ... }
//!```
//!
//!Besides the input state, satisfy's only parameter is a predicate function and will succeed only if the next piece of input satisfies the supplied predicate. Here's an example that might be used in the `parse` macro.
//!
//!```
//!    satisfy(|c| {
//!        match c {
//!            b'c' | b'h' | b'a' | b'r' => true,
//!            _ => false,
//!        }
//!    })
//!```
//!    This parser will only succeed if the character is one of the characters in "char".
//!
//!    Lastly, here is the parser combinator `count`, which will attempt to run a parser a number of times on its input.
//!
//!```
//!pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResult<'a, I, T, E>
//!  where I: Copy,
//!        U: 'a,
//!        F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
//!        T: FromIterator<U> { ... }
//!```
//!This combinator construcs an iterator that will match elements `num` times, and collect them into any datatype you want.

//!Using parsers is almost entirely done using the `parse!` macro, which enables us to do three distinct things:
//!* Sequence parsers over the remaining input
//!* Store intermediate results into datatypes
//!* Return a datatype at the end, which may be the result of any arbitrary computation over the intermediate results.

//!In other words, just as a normal Rust function usually looks something like
//!```
//!fn f() -> (u8, u8, u8) {
//!    let a = 3;
//!    let b = 3;
//!    launch_missiles();
//!    return (a, b, a + b);
//!}
//!```
//!
//!A Chomp parser looks something like
//!
//!```
//!fn f<'a>(i: Input<'a, u8>) -> SimpleResult<'a, I, (u8, u8, u8)> {
//!    parse!{i;
//!        let a = token(b'3');
//!        let b = token(b'3')
//!        string(b"missiles");
//!        ret (a, b, a + b)
//!    }
//!}
//!```
//!Readers familiar with Haskell or F# will recognize this as a "monadic computation" or "computation expression".
//!
//!    You use the `parse!` macro as follows:
//!- Write the input parameter first, with a semicolon.
//!- Write any number of valid parser actions or identifier bindings, where:
//!    - a parser action takes the form `parser(params*)`, with the input parameter omitted.
//!    - an identifier binding takes the form `let identifer = parser(params*);`, with the input parameter omitted.
//!- Write the final line of the macro, which must always be either a parser action, or a return statement which takes the form `ret expression`. The type of `expression` becomes the return type of the entire parser, should it succeed.
//!The entire grammar for the macro is listed elsewhere in this documentation.

use ::std::fmt;

#[macro_use]
mod macros;
mod iter;
mod aliases;

pub mod internal;
pub mod parsers;
pub mod combinators;

pub use combinators::{
    count,
    option,
    or,
    many,
    many1,
    skip_many,
};
pub use parsers::{
    any,
    not_token,
    peek,
    satisfy,
    string,
    take,
    take_remainder,
    take_till,
    take_while,
    take_while1,
    token,
};
pub use aliases::{
    U8Result,
    SimpleResult,
};
pub use err::Error;
pub use iter::Iter;

use internal::State;

/// Linear type containing the parser state, this type is threaded though `bind`.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct Input<'a, I: 'a>(&'a [I]);

impl<'a, I> Input<'a, I> {
    /// Creates a new input to be passed to parsers and/or combinators.
    pub fn new(i: &'a [I]) -> Self {
        Input(i)
    }

    /// Returns the value `t` with the input context.
    pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
        internal::data(self.0, t)
    }

    /// Returns the error value `e` with the input context.
    pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
        internal::error(self.0, e)
    }
}

/// The basic return type of a parser.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct ParseResult<'a, I: 'a, T: 'a, E: 'a>(State<'a, I, T, E>);

impl<'a, I, T, E> ParseResult<'a, I, T, E> {
    pub fn bind<F, U, V = E>(self, f: F) -> ParseResult<'a, I, U, V>
      where F: FnOnce(Input<'a, I>, T) -> ParseResult<'a, I, U, V>,
            V: From<E> {
        match self.0 {
            State::Data(i, t)    => f(Input(i), t).map_err(From::from),
            State::Error(i, e)   => ParseResult(State::Error(i, From::from(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    pub fn map<U, F>(self, f: F) -> ParseResult<'a, I, U, E>
      where F: FnOnce(T) -> U {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, f(t))),
            State::Error(i, e)   => ParseResult(State::Error(i, e)),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    pub fn map_err<V, F>(self, f: F) -> ParseResult<'a, I, T, V>
      where F: FnOnce(E) -> V {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, t)),
            State::Error(i, e)   => ParseResult(State::Error(i, f(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }
}

impl<'a, I, T, E: fmt::Debug> ParseResult<'a, I, T, E> {
    /// Extracts the contained type if the parser is in a success-state, panics otherwise.
    #[inline]
    pub fn unwrap(self) -> T {
        match self.0 {
            State::Data(_, t)    => t,
            State::Error(_, e)   => panic!("called `Parser::unwrap` on a parser in an error state: {:?}", e),
            State::Incomplete(_) => panic!("called `Parser::unwrap` on a parser in an incomplete state"),
        }
    }
}

impl<'a, I, T: fmt::Debug, E> ParseResult<'a, I, T, E> {
    pub fn unwrap_err(self) -> E {
        match self.0 {
            State::Data(_, t)    => panic!("called `Parser::unwrap_err` on a parser in a success state: {:?}", t),
            State::Error(_, e)   => e,
            State::Incomplete(_) => panic!("called `Parser::unwrap_err` on a parser in an incomplete state"),
        }
    }
}

#[cfg(feature = "verbose_error")]
mod err {
    //! This is a private module to contain the more verbose error type as well as adapters for
    //! using it.
    //!
    //! All adapters are #[inline(always)] and will construct the appropriate error type.
    use std::any;
    use std::error;
    use std::fmt;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub enum Error<I> {
        Expected(I),
        Unexpected,
        String(Vec<I>),
    }

    impl<I> fmt::Display for Error<I>
      where I: fmt::Debug {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                Error::Expected(ref c) => write!(f, "expected {:?}", *c),
                Error::Unexpected      => write!(f, "unexpected"),
                Error::String(ref s)   => write!(f, "expected {:?}", *s),
            }
        }
    }

    impl<I> error::Error for Error<I>
      where I: any::Any + fmt::Debug {
        fn description(&self) -> &str {
            match *self {
                Error::Expected(_) => "expected a certain token, received another",
                Error::Unexpected  => "received an unexpected token",
                Error::String(_)   => "expected a certain string of tokens, encountered an unexpected token",
            }
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error::Unexpected
    }

    #[inline(always)]
    pub fn expected<'a, I>(i: I) -> Error<I> {
        Error::Expected(i)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], _offset: usize, expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(buffer, Error::String(expected.to_vec()))
    }
}

#[cfg(not(feature = "verbose_error"))]
mod err {
    //! This is a private module to contain the smaller error type as well as adapters for using
    //! it.
    //!
    //! All adapters are #[inline(always)], and will just noop the data.
    use ::std::any;
    use ::std::error;
    use ::std::fmt;

    use ::std::marker::PhantomData;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub struct Error<I>(PhantomData<I>);

    impl<I: fmt::Debug> fmt::Display for Error<I> {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(f, "generic parse error (chomp was compiled without --feature verbose_error)")
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            "generic parse error (chomp was compiled without --feature verbose_error)"
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn expected<'a, I>(_: I) -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], offset: usize, _expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(&buffer[offset..], Error(PhantomData))
    }
}
<commit_msg>Added initial documentation.<commit_after>//! Chomp is an alternative parser combinator library for the Rust programming language. It was written as the culmination of the experiments detailed in these blog posts:
//!
//! * [Part 1](http://m4rw3r.github.io/parser-combinator-experiments-rust/)
//! * [Part 2](http://m4rw3r.github.io/parser-combinator-experiments-errors)
//! * [Part 3](http://m4rw3r.github.io/parser-combinator-experiments-part-3)
//!
//! For its current capabilities, you will find that Chomp performs consistently as well, if not better, than optimized C parsers, while being vastly more expressive. For an example that builds a performant HTTP parser out of smaller parsers, see [http_parser.rs](examples/http_parser.rs).
//! # Example
//!
//! ```
//! use chomp::{Input, ParseResult, Error};
//! use chomp::{take_while1, token};
//!
//! let i = Input::new("martin wernstål\n".as_bytes());
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Name<'a> {
//!     first: &'a [u8],
//!     last:  &'a [u8],
//! }
//!
//! fn name(i: Input<u8>) -> ParseResult<u8, Name, Error<u8>> {
//!     take_while1(i, |c| c != b' ').bind(|i, first|
//!         token(i, b' ').bind(|i, _| // skipping this char
//!             take_while1(i, |c| c != b'\n').bind(|i, last|
//!                 i.ret(Name{
//!                     first: first,
//!                     last:  last,
//!                 }))))
//! }
//!
//! assert_eq!(name(i).unwrap(), Name{first: b"martin", last: "wernstål".as_bytes()});
//! ```
//!
//! # Usage
//! Chomp's functionality is split between three modules.
//!
//! * `parsers` contains the basic parsers used to parse streams of input.
//! * `combinators` contains functions which take parsers and return new ones.
//! * `internal` contains the building blocks used to make new parsers. This is advanced usage and is far more involved than using the pre-existing parsers, but is sometimes unavoidable.
//!
//! A parser is, at its simplest, a function that takes a slice of input and returns a `ParserResult<'a, I, T, E>`, where I, T, and E are the input, output, and error types, respectively. Parsers are usually parameterized over values or other parsers as well, so these appear as extra arguments in the parsing function. As an example, here is the signature of the `token` parser, which matches a particular input.
//!
//! ```
//! fn token<'a, I: 'a + Copy + Eq>(i: Input<'a, I>, t: I) -> SimpleResult<'a, I, I> {...}
//! ```
//!
//!   Notice that the first argument is an `Input<'a, I>`, and the second argument is some `I`. `Input<'a,I>` is just a datatype over the current state of the parser and a slice of input `I`, and prevents the parser writer from accidentally mutating the state of the parser. Later, when we introduce the `parse!` macro, we will see that using a parser in this macro just means supplying all of the arguments but the input, as so:
//! ```
//! token(b'T');
//! ```
//! Note that you cannot do this outside of the `parse!` macro.
//! `SimpleResult<'a, I, T>` is a convenience type alias over `Result<'a, I, T, Error<u8>>`, and `Error<I>` is just a convenient "default" error type that will be sufficient for most uses. For more sophisticated usage, one can always write a custom error type.
//!
//!    A very useful parser is the `satisfy` parser:
//!
//! ```
//! fn satisfy<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, I>
//!    where F: FnOnce(I) -> bool { ... }
//! ```
//!
//! Besides the input state, satisfy's only parameter is a predicate function and will succeed only if the next piece of input satisfies the supplied predicate. Here's an example that might be used in the `parse!` macro.
//!
//! ```
//!    satisfy(|c| {
//!        match c {
//!            b'c' | b'h' | b'a' | b'r' => true,
//!            _ => false,
//!        }
//!    });
//! ```
//!    This parser will only succeed if the character is one of the characters in "char".
//!
//!    Lastly, here is the parser combinator `count`, which will attempt to run a parser a number of times on its input.
//!
//! ```
//! pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResult<'a, I, T, E>
//!   where I: Copy,
//!         U: 'a,
//!         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
//!         T: FromIterator<U> { ... }
//! ```
//!
//! Using parsers is almost entirely done using the `parse!` macro, which enables us to do three distinct things:
//!
//! * Sequence parsers over the remaining input
//! * Store intermediate results into datatypes
//! * Return a datatype at the end, which may be the result of any arbitrary computation over the intermediate results.
//!
//! In other words, just as a normal Rust function usually looks something like
//!
//! ```
//! fn f() -> (u8, u8, u8) {
//!     let a = 3;
//!     let b = 3;
//!     launch_missiles();
//!     return (a, b, a + b);
//! }
//! ```
//!
//! A Chomp parser looks something like
//!
//! ```
//! fn f<'a>(i: Input<'a, u8>) -> SimpleResult<'a, I, (u8, u8, u8)> {
//!     parse!{i;
//!         let a = token(b'3');
//!         let b = token(b'3')
//!         string(b"missiles");
//!         ret (a, b, a + b)
//!     }
//! }
//! ```
//! Readers familiar with Haskell or F# will recognize this as a "monadic computation" or "computation expression".
//!
//! You use the `parse!` macro as follows:
//!
//! - Write the input parameter first, with a semicolon.
//! - Write any number of valid parser actions or identifier bindings, where:
//!    - a parser action takes the form `parser(params*)`, with the input parameter omitted.
//!    - an identifier binding takes the form `let identifer = parser(params*);`, with the input parameter omitted.
//! - Write the final line of the macro, which must always be either a parser action, or a return statement which takes the form `ret expression`. The type of `expression` becomes the return type of the entire parser, should it succeed.
//! The entire grammar for the macro is listed elsewhere in this documentation.

use ::std::fmt;

#[macro_use]
mod macros;
mod iter;
mod aliases;

pub mod internal;
pub mod parsers;
pub mod combinators;

pub use combinators::{
    count,
    option,
    or,
    many,
    many1,
    skip_many,
};
pub use parsers::{
    any,
    not_token,
    peek,
    satisfy,
    string,
    take,
    take_remainder,
    take_till,
    take_while,
    take_while1,
    token,
};
pub use aliases::{
    U8Result,
    SimpleResult,
};
pub use err::Error;
pub use iter::Iter;

use internal::State;

/// Linear type containing the parser state, this type is threaded though `bind`.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct Input<'a, I: 'a>(&'a [I]);

impl<'a, I> Input<'a, I> {
    /// Creates a new input to be passed to parsers and/or combinators.
    pub fn new(i: &'a [I]) -> Self {
        Input(i)
    }

    /// Returns the value `t` with the input context.
    pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
        internal::data(self.0, t)
    }

    /// Returns the error value `e` with the input context.
    pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
        internal::error(self.0, e)
    }
}

/// The basic return type of a parser.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct ParseResult<'a, I: 'a, T: 'a, E: 'a>(State<'a, I, T, E>);

impl<'a, I, T, E> ParseResult<'a, I, T, E> {
    pub fn bind<F, U, V = E>(self, f: F) -> ParseResult<'a, I, U, V>
      where F: FnOnce(Input<'a, I>, T) -> ParseResult<'a, I, U, V>,
            V: From<E> {
        match self.0 {
            State::Data(i, t)    => f(Input(i), t).map_err(From::from),
            State::Error(i, e)   => ParseResult(State::Error(i, From::from(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    pub fn map<U, F>(self, f: F) -> ParseResult<'a, I, U, E>
      where F: FnOnce(T) -> U {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, f(t))),
            State::Error(i, e)   => ParseResult(State::Error(i, e)),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    pub fn map_err<V, F>(self, f: F) -> ParseResult<'a, I, T, V>
      where F: FnOnce(E) -> V {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, t)),
            State::Error(i, e)   => ParseResult(State::Error(i, f(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }
}

impl<'a, I, T, E: fmt::Debug> ParseResult<'a, I, T, E> {
    /// Extracts the contained type if the parser is in a success-state, panics otherwise.
    #[inline]
    pub fn unwrap(self) -> T {
        match self.0 {
            State::Data(_, t)    => t,
            State::Error(_, e)   => panic!("called `Parser::unwrap` on a parser in an error state: {:?}", e),
            State::Incomplete(_) => panic!("called `Parser::unwrap` on a parser in an incomplete state"),
        }
    }
}

impl<'a, I, T: fmt::Debug, E> ParseResult<'a, I, T, E> {
    pub fn unwrap_err(self) -> E {
        match self.0 {
            State::Data(_, t)    => panic!("called `Parser::unwrap_err` on a parser in a success state: {:?}", t),
            State::Error(_, e)   => e,
            State::Incomplete(_) => panic!("called `Parser::unwrap_err` on a parser in an incomplete state"),
        }
    }
}

#[cfg(feature = "verbose_error")]
mod err {
    //! This is a private module to contain the more verbose error type as well as adapters for
    //! using it.
    //!
    //! All adapters are #[inline(always)] and will construct the appropriate error type.
    use std::any;
    use std::error;
    use std::fmt;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub enum Error<I> {
        Expected(I),
        Unexpected,
        String(Vec<I>),
    }

    impl<I> fmt::Display for Error<I>
      where I: fmt::Debug {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                Error::Expected(ref c) => write!(f, "expected {:?}", *c),
                Error::Unexpected      => write!(f, "unexpected"),
                Error::String(ref s)   => write!(f, "expected {:?}", *s),
            }
        }
    }

    impl<I> error::Error for Error<I>
      where I: any::Any + fmt::Debug {
        fn description(&self) -> &str {
            match *self {
                Error::Expected(_) => "expected a certain token, received another",
                Error::Unexpected  => "received an unexpected token",
                Error::String(_)   => "expected a certain string of tokens, encountered an unexpected token",
            }
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error::Unexpected
    }

    #[inline(always)]
    pub fn expected<'a, I>(i: I) -> Error<I> {
        Error::Expected(i)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], _offset: usize, expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(buffer, Error::String(expected.to_vec()))
    }
}

#[cfg(not(feature = "verbose_error"))]
mod err {
    //! This is a private module to contain the smaller error type as well as adapters for using
    //! it.
    //!
    //! All adapters are #[inline(always)], and will just noop the data.
    use ::std::any;
    use ::std::error;
    use ::std::fmt;

    use ::std::marker::PhantomData;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub struct Error<I>(PhantomData<I>);

    impl<I: fmt::Debug> fmt::Display for Error<I> {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(f, "generic parse error (chomp was compiled without --feature verbose_error)")
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            "generic parse error (chomp was compiled without --feature verbose_error)"
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn expected<'a, I>(_: I) -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], offset: usize, _expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(&buffer[offset..], Error(PhantomData))
    }
}
<|endoftext|>


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

//! Abstraction of a thread pool for basic parallelism.

use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex};
use std::thread;

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    thread_counter: &'a Arc<Mutex<usize>>,
    thread_count_max: &'a Arc<Mutex<usize>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
           thread_counter: &'a Arc<Mutex<usize>>,
           thread_count_max: &'a Arc<Mutex<usize>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            thread_counter: thread_counter,
            thread_count_max: thread_count_max,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            *self.thread_counter.lock().unwrap() -= 1;
            spawn_in_pool(self.jobs.clone(), self.thread_counter.clone(), self.thread_count_max.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
#[derive(Clone)]
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>,
    job_receiver: Arc<Mutex<Receiver<Thunk<'static>>>>,
    active_count: Arc<Mutex<usize>>,
    max_count: Arc<Mutex<usize>>,
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));
        let active_count = Arc::new(Mutex::new(0));
        let max_count = Arc::new(Mutex::new(threads));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone(), active_count.clone(), max_count.clone());
        }

        ThreadPool {
            jobs: tx,
            job_receiver: rx.clone(),
            active_count: active_count,
            max_count: max_count
        }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }

    /// Returns the number of currently active threads.
    pub fn active_count(&self) -> usize {
        *self.active_count.lock().unwrap()
    }

    /// Returns the number of created threads
    pub fn max_count(&self) -> usize {
        *self.max_count.lock().unwrap()
    }

    /// Sets the number of threads to use as `threads`.
    /// Can be used to change the threadpool size during runtime
    pub fn set_threads(&mut self, threads: usize) {
        assert!(threads >= 1);
        let current_max = self.max_count.lock().unwrap().clone();
        *self.max_count.lock().unwrap() = threads;
        if threads > current_max {
            // Spawn new threads
            for _ in 0..(threads - current_max) {
                spawn_in_pool(self.job_receiver.clone(), self.active_count.clone(), self.max_count.clone());
            }
        }
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>,
                 thread_counter: Arc<Mutex<usize>>,
                 thread_count_max: Arc<Mutex<usize>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs, &thread_counter, &thread_count_max);

        loop {
            // clone values so that the mutexes are not held
            let thread_counter_val = thread_counter.lock().unwrap().clone();
            let thread_count_max_val = thread_count_max.lock().unwrap().clone();
            if thread_counter_val < thread_count_max_val {
                let message = {
                    // Only lock jobs for the time it takes
                    // to get a job, not run it.
                    let lock = jobs.lock().unwrap();
                    lock.recv()
                };

                match message {
                    Ok(job) => {
                        *thread_counter.lock().unwrap() += 1;
                        job.call_box();
                        *thread_counter.lock().unwrap() -= 1;
                    },

                    // The Threadpool was dropped.
                    Err(..) => break
                }
            } else {
                break;
            }
        }

        sentinel.cancel();
    });
}

#[cfg(test)]
mod test {
    #![allow(deprecated)]
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};
    use std::thread::sleep_ms;

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_set_threads_increasing() {
        let new_thread_amount = 6;
        let mut pool = ThreadPool::new(TEST_TASKS);
        for _ in 0..TEST_TASKS {
            pool.execute(move || {
                loop {
                    sleep_ms(10000)
                }
            });
        }
        pool.set_threads(new_thread_amount);
        for _ in 0..(new_thread_amount - TEST_TASKS) {
            pool.execute(move || {
                loop {
                    sleep_ms(10000)
                }
            });
        }
        sleep_ms(1000);
        assert_eq!(pool.active_count(), new_thread_amount);
    }

    #[test]
    fn test_set_threads_decreasing() {
        let new_thread_amount = 2;
        let mut pool = ThreadPool::new(TEST_TASKS);
        for _ in 0..TEST_TASKS {
            pool.execute(move || {
                1 + 1;
            });
        }
        pool.set_threads(new_thread_amount);
        for _ in 0..new_thread_amount {
            pool.execute(move || {
                loop {
                    sleep_ms(10000)
                }
            });
        }
        sleep_ms(1000);
        assert_eq!(pool.active_count(), new_thread_amount);
    }

    #[test]
    fn test_active_count() {
        let pool = ThreadPool::new(TEST_TASKS);
        for _ in 0..TEST_TASKS {
            pool.execute(move|| {
                loop {
                    sleep_ms(10000);
                }
            });
        }
        sleep_ms(1000);
        let active_count = pool.active_count();
        assert_eq!(active_count, TEST_TASKS);
        let initialized_count = pool.max_count();
        assert_eq!(initialized_count, TEST_TASKS);
    }

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}
<commit_msg>Switch active_count from Mutex to RwLock for more performance<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a thread pool for basic parallelism.

use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, RwLock};
use std::thread;

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    thread_counter: &'a Arc<RwLock<usize>>,
    thread_count_max: &'a Arc<Mutex<usize>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
           thread_counter: &'a Arc<RwLock<usize>>,
           thread_count_max: &'a Arc<Mutex<usize>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            thread_counter: thread_counter,
            thread_count_max: thread_count_max,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            *self.thread_counter.write().unwrap() -= 1;
            spawn_in_pool(self.jobs.clone(), self.thread_counter.clone(), self.thread_count_max.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
#[derive(Clone)]
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>,
    job_receiver: Arc<Mutex<Receiver<Thunk<'static>>>>,
    active_count: Arc<RwLock<usize>>,
    max_count: Arc<Mutex<usize>>,
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));
        let active_count = Arc::new(RwLock::new(0));
        let max_count = Arc::new(Mutex::new(threads));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone(), active_count.clone(), max_count.clone());
        }

        ThreadPool {
            jobs: tx,
            job_receiver: rx.clone(),
            active_count: active_count,
            max_count: max_count
        }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }

    /// Returns the number of currently active threads.
    pub fn active_count(&self) -> usize {
        *self.active_count.read().unwrap()
    }

    /// Returns the number of created threads
    pub fn max_count(&self) -> usize {
        *self.max_count.lock().unwrap()
    }

    /// Sets the number of threads to use as `threads`.
    /// Can be used to change the threadpool size during runtime
    pub fn set_threads(&mut self, threads: usize) {
        assert!(threads >= 1);
        let current_max = self.max_count.lock().unwrap().clone();
        *self.max_count.lock().unwrap() = threads;
        if threads > current_max {
            // Spawn new threads
            for _ in 0..(threads - current_max) {
                spawn_in_pool(self.job_receiver.clone(), self.active_count.clone(), self.max_count.clone());
            }
        }
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>,
                 thread_counter: Arc<RwLock<usize>>,
                 thread_count_max: Arc<Mutex<usize>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs, &thread_counter, &thread_count_max);

        loop {
            // clone values so that the mutexes are not held
            let thread_counter_val = thread_counter.read().unwrap().clone();
            let thread_count_max_val = thread_count_max.lock().unwrap().clone();
            if thread_counter_val < thread_count_max_val {
                let message = {
                    // Only lock jobs for the time it takes
                    // to get a job, not run it.
                    let lock = jobs.lock().unwrap();
                    lock.recv()
                };

                match message {
                    Ok(job) => {
                        *thread_counter.write().unwrap() += 1;
                        job.call_box();
                        *thread_counter.write().unwrap() -= 1;
                    },

                    // The Threadpool was dropped.
                    Err(..) => break
                }
            } else {
                break;
            }
        }

        sentinel.cancel();
    });
}

#[cfg(test)]
mod test {
    #![allow(deprecated)]
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};
    use std::thread::sleep_ms;

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_set_threads_increasing() {
        let new_thread_amount = 6;
        let mut pool = ThreadPool::new(TEST_TASKS);
        for _ in 0..TEST_TASKS {
            pool.execute(move || {
                loop {
                    sleep_ms(10000)
                }
            });
        }
        pool.set_threads(new_thread_amount);
        for _ in 0..(new_thread_amount - TEST_TASKS) {
            pool.execute(move || {
                loop {
                    sleep_ms(10000)
                }
            });
        }
        sleep_ms(1000);
        assert_eq!(pool.active_count(), new_thread_amount);
    }

    #[test]
    fn test_set_threads_decreasing() {
        let new_thread_amount = 2;
        let mut pool = ThreadPool::new(TEST_TASKS);
        for _ in 0..TEST_TASKS {
            pool.execute(move || {
                1 + 1;
            });
        }
        pool.set_threads(new_thread_amount);
        for _ in 0..new_thread_amount {
            pool.execute(move || {
                loop {
                    sleep_ms(10000)
                }
            });
        }
        sleep_ms(1000);
        assert_eq!(pool.active_count(), new_thread_amount);
    }

    #[test]
    fn test_active_count() {
        let pool = ThreadPool::new(TEST_TASKS);
        for _ in 0..TEST_TASKS {
            pool.execute(move|| {
                loop {
                    sleep_ms(10000);
                }
            });
        }
        sleep_ms(1000);
        let active_count = pool.active_count();
        assert_eq!(active_count, TEST_TASKS);
        let initialized_count = pool.max_count();
        assert_eq!(initialized_count, TEST_TASKS);
    }

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}
<|endoftext|>


<commit_before>mod platform;
mod farmhashna;
mod farmhashmk;
mod farmhashuo;
mod farmhashxo;
mod farmhashna_shared;
mod farmhashcc_shared;
mod farmhashmk_shared;

use farmhashmk::mk_hash32;
use farmhashmk::mk_hash32_with_seed;
use farmhashxo::xo_hash64;
use farmhashxo::xo_hash64_with_seed;
use farmhashxo::xo_hash64_with_seeds;
use std::hash::Hasher;

/// Create a new farmhash based u32 for an array of bytes.
///
/// # Examples
///
/// ```
/// let value: &str = "hello world";
/// let res32 = farmhash::hash32(&value.as_bytes());
/// //res32 ==> 430397466
/// ```
pub fn hash32(s: &[u8]) -> u32 {
    mk_hash32(s)
}
/// Create a new farmhash based u32 for an array of bytes with a given seed.
pub fn hash32_with_seed(s: &[u8], seed: u32) -> u32 {
    mk_hash32_with_seed(s, seed)
}

/// Create a new farmhash based u64 for an array of bytes.
///
/// # Examples
///
/// ```
/// let value: &str = "hello world";
/// let res64 = farmhash::hash64(&value.as_bytes());
/// //res64 ==> 6381520714923946011
/// ```
pub fn hash64(s: &[u8]) -> u64 {
    xo_hash64(s)
}

/// Create a new farmhash based u64 for an array of bytes with a given seed.
pub fn hash64_with_seed(s: &[u8], seed: u64) -> u64 {
    xo_hash64_with_seed(s, seed)
}

/// Create a new farmhash based u64 for an array of bytes with 2 given seeds.
pub fn hash64_with_seeds(s: &[u8], seed0: u64, seed1: u64) -> u64 {
    xo_hash64_with_seeds(s, seed0, seed1)
}

pub struct FarmHasher {
    bytes: Vec<u8>
}

impl Default for FarmHasher {
    #[inline]
    fn default() -> FarmHasher { FarmHasher{bytes: Vec::with_capacity(20)} }
}

impl Hasher for FarmHasher {
    #[inline]
    fn finish(&self) -> u64 {
        hash64(&self.bytes[..])
    }
    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        self.bytes.extend(bytes.iter().cloned());
    }
}
<commit_msg>Expose stable, “fingerprinting” hash functions<commit_after>mod platform;
mod farmhashna;
mod farmhashmk;
mod farmhashuo;
mod farmhashxo;
mod farmhashna_shared;
mod farmhashcc_shared;
mod farmhashmk_shared;

use farmhashna::na_hash64;
use farmhashmk::mk_hash32;
use farmhashmk::mk_hash32_with_seed;
use farmhashxo::xo_hash64;
use farmhashxo::xo_hash64_with_seed;
use farmhashxo::xo_hash64_with_seeds;
use std::hash::Hasher;

/// Create a new farmhash based u32 for an array of bytes.
///
/// # Examples
///
/// ```
/// let value: &str = "hello world";
/// let res32 = farmhash::hash32(&value.as_bytes());
/// //res32 ==> 430397466
/// ```
pub fn hash32(s: &[u8]) -> u32 {
    mk_hash32(s)
}
/// Create a new farmhash based u32 for an array of bytes with a given seed.
pub fn hash32_with_seed(s: &[u8], seed: u32) -> u32 {
    mk_hash32_with_seed(s, seed)
}

/// Create a new farmhash based u64 for an array of bytes.
///
/// # Examples
///
/// ```
/// let value: &str = "hello world";
/// let res64 = farmhash::hash64(&value.as_bytes());
/// //res64 ==> 6381520714923946011
/// ```
pub fn hash64(s: &[u8]) -> u64 {
    xo_hash64(s)
}

/// Create a new farmhash based u64 for an array of bytes with a given seed.
pub fn hash64_with_seed(s: &[u8], seed: u64) -> u64 {
    xo_hash64_with_seed(s, seed)
}

/// Create a new farmhash based u64 for an array of bytes with 2 given seeds.
pub fn hash64_with_seeds(s: &[u8], seed0: u64, seed1: u64) -> u64 {
    xo_hash64_with_seeds(s, seed0, seed1)
}

/// Create a stable farmhash based u32 for an array of bytes.
///
/// # Examples
///
/// ```
/// let value: &str = "hello world";
/// let res32 = farmhash::fingerprint32(&value.as_bytes());
/// //res32 ==> 430397466
/// ```
pub fn fingerprint32(s: &[u8]) -> u32 {
    mk_hash32(s)
}

/// Create a stable farmhash based u64 for an array of bytes.
///
/// # Examples
///
/// ```
/// let value: &str = "hello world";
/// let res64 = farmhash::fingerprint64(&value.as_bytes());
/// //res64 ==> 6381520714923946011
/// ```
pub fn fingerprint64(s: &[u8]) -> u64 {
    na_hash64(s)
}

pub struct FarmHasher {
    bytes: Vec<u8>
}

impl Default for FarmHasher {
    #[inline]
    fn default() -> FarmHasher { FarmHasher{bytes: Vec::with_capacity(20)} }
}

impl Hasher for FarmHasher {
    #[inline]
    fn finish(&self) -> u64 {
        hash64(&self.bytes[..])
    }
    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        self.bytes.extend(bytes.iter().cloned());
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::{File, OpenOptions};
use std::process::Command;
use std::process::Stdio;
use std::path::Path;
use std::os::unix::prelude::AsRawFd;
use libc::{c_ushort, c_int, c_ulong};
use std::str;
use std::os::unix::prelude::FromRawFd;
use std::cmp::min;

pub struct TTY {
    file: File,
    dimensions: (usize, usize),
    original_state: String
}

pub trait IO {
    fn write(&mut self, line: &str);
    fn read(&mut self) -> Option<String>;
    fn last(&self) -> &str;
    fn lines(&self) -> Vec<String>;
    fn dimensions(&self) -> (usize, usize);
    fn reset(&self);
}

impl IO for TTY {
    fn write(&mut self, line: &str) {

        let it = self.trim(line);
        match self.file.write(it.as_bytes()) {
            Ok(k) => { k },
            Err(e) => { panic!(e.to_string()) }
        };
    }

    fn read(&mut self) -> Option<String> {
        let mut buffer = [0] ;
        let res = match self.file.read(&mut buffer) {
            Ok(c) if  c > 0 => {
                str::from_utf8(&buffer).ok().map(|x| x.to_string())
            },
            _ => None,
        };
        res
    }

    fn last(&self) -> &str {
        "fail"
    }

    fn lines(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();
        lines.push("fail".to_string());
        lines
    }

    fn dimensions(&self) -> (usize, usize) {
        self.dimensions
    }

    fn reset(&self) {
        TTY::stty(&self.file, &[self.original_state.as_ref()]);
    }
}

impl TTY {
    pub fn new() -> TTY {
        let path = Path::new("/dev/tty");
        let file = OpenOptions::new().read(true).write(true).append(true).open(&path).unwrap();
        let dimension = TTY::get_window_size(&file);
        let orig_state = TTY::previous_state(&file);

        TTY::no_echo_no_escaping(&file);

        TTY {
            original_state: orig_state,
            dimensions: dimension,
            file: file,
        }
    }

    fn trim(&self, line: &str) -> String {
        let actual = min(line.len(), self.dimensions.0);
        line[..actual].into()
    }

    fn get_window_size(file: &File) -> (usize, usize) {
        extern {
            fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
        }
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const TIOCGWINSZ: c_ulong = 0x40087468;

        #[cfg(any(target_os = "linux", target_os = "android"))]
        const TIOCGWINSZ: c_ulong = 0x00005413;

        #[repr(C)]
        struct TermSize {
            rows: c_ushort,
            cols: c_ushort,
            x: c_ushort,
            y: c_ushort,
        }

        let size = TermSize { rows: 0, cols: 0, x: 0, y: 0 };
        if unsafe { ioctl(file.as_raw_fd(), TIOCGWINSZ, &size) } == 0 {
            (size.cols as usize, size.rows as usize)
        } else {
            panic!("Could not read winsize from /dev/tty")
        }
    }

    fn stty(file: &File, args: &[&str]) -> Option<String> {
        extern { fn dup2(src: c_int, dst: c_int) -> c_int;  }
        unsafe {
            // This is a hack until a replacement for InheritFd from old_io is available.
            let raw_fd = file.as_raw_fd();
            dup2(raw_fd, 0);
            match Command::new("stty").args(args).stdin(Stdio::inherit()).output() {
                Err(k) => { panic!("something got fucked when reading stty") }
                Ok(output) => { String::from_utf8(output.stdout).ok() }
            }
        }
    }

    fn no_echo_no_escaping(file: &File) {
        TTY::stty(file, &["-echo", "-icanon"]);
    }

    fn previous_state(file: &File) -> String {
        TTY::stty(file, &["-g"]).unwrap_or("".to_string())
    }
}
<commit_msg>Squish some warnings<commit_after>use std::io::prelude::*;
use std::fs::{File, OpenOptions};
use std::process::Command;
use std::process::Stdio;
use std::path::Path;
use std::os::unix::prelude::AsRawFd;
use libc::{c_ushort, c_int, c_ulong};
use std::str;
use std::cmp::min;

pub struct TTY {
    file: File,
    dimensions: (usize, usize),
    original_state: String
}

pub trait IO {
    fn write(&mut self, line: &str);
    fn read(&mut self) -> Option<String>;
    fn last(&self) -> &str;
    fn lines(&self) -> Vec<String>;
    fn dimensions(&self) -> (usize, usize);
    fn reset(&self);
}

impl IO for TTY {
    fn write(&mut self, line: &str) {

        let it = self.trim(line);
        match self.file.write(it.as_bytes()) {
            Ok(k) => { k },
            Err(e) => { panic!(e.to_string()) }
        };
    }

    fn read(&mut self) -> Option<String> {
        let mut buffer = [0] ;
        let res = match self.file.read(&mut buffer) {
            Ok(c) if  c > 0 => {
                str::from_utf8(&buffer).ok().map(|x| x.to_string())
            },
            _ => None,
        };
        res
    }

    fn last(&self) -> &str {
        "fail"
    }

    fn lines(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();
        lines.push("fail".to_string());
        lines
    }

    fn dimensions(&self) -> (usize, usize) {
        self.dimensions
    }

    fn reset(&self) {
        TTY::stty(&self.file, &[self.original_state.as_ref()]);
    }
}

impl TTY {
    pub fn new() -> TTY {
        let path = Path::new("/dev/tty");
        let file = OpenOptions::new().read(true).write(true).append(true).open(&path).unwrap();
        let dimension = TTY::get_window_size(&file);
        let orig_state = TTY::previous_state(&file);

        TTY::no_echo_no_escaping(&file);

        TTY {
            original_state: orig_state,
            dimensions: dimension,
            file: file,
        }
    }

    fn trim(&self, line: &str) -> String {
        let actual = min(line.len(), self.dimensions.0);
        line[..actual].into()
    }

    fn get_window_size(file: &File) -> (usize, usize) {
        extern {
            fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
        }
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const TIOCGWINSZ: c_ulong = 0x40087468;

        #[cfg(any(target_os = "linux", target_os = "android"))]
        const TIOCGWINSZ: c_ulong = 0x00005413;

        #[repr(C)]
        struct TermSize {
            rows: c_ushort,
            cols: c_ushort,
            x: c_ushort,
            y: c_ushort,
        }

        let size = TermSize { rows: 0, cols: 0, x: 0, y: 0 };
        if unsafe { ioctl(file.as_raw_fd(), TIOCGWINSZ, &size) } == 0 {
            (size.cols as usize, size.rows as usize)
        } else {
            panic!("Could not read winsize from /dev/tty")
        }
    }

    fn stty(file: &File, args: &[&str]) -> Option<String> {
        extern { fn dup2(src: c_int, dst: c_int) -> c_int;  }
        unsafe {
            // This is a hack until a replacement for InheritFd from old_io is available.
            let raw_fd = file.as_raw_fd();
            dup2(raw_fd, 0);
            match Command::new("stty").args(args).stdin(Stdio::inherit()).output() {
                Err(k) => { panic!(k.to_string()) }
                Ok(output) => { String::from_utf8(output.stdout).ok() }
            }
        }
    }

    fn no_echo_no_escaping(file: &File) {
        TTY::stty(file, &["-echo", "-icanon"]);
    }

    fn previous_state(file: &File) -> String {
        TTY::stty(file, &["-g"]).unwrap_or("".to_string())
    }
}
<|endoftext|>