<commit_before>extern crate curl;

use std::str;
use curl::http;

mod util;

pub struct Firebase {
    base_uri: String,
}

impl Firebase {
    pub fn new(base_uri: &str) -> Self {
        Firebase {
            base_uri: base_uri.to_string(),
        }
    }

    pub fn authenticated(base_uri: &str, auth_token: &str) -> Self {
        let uri = util::trim_right(base_uri, "/");
        Firebase {
            base_uri: format!("{}&auth={}", uri, auth_token)
        }
    }

    pub fn at(&self, path: &str) -> Self {
        let mut components = self.base_uri.split('&');

        let base = components.next().unwrap();
        let base = util::trim_right(base, ".json");
        let path = util::add_right(path, ".json");
        let url  = util::join(base, &path, "/");

        let url = if let Some(args) = components.next() {
            url + "&" + args
        } else {
            url
        };

        Firebase {
            base_uri: url
        }
    }

    pub fn get(&self) -> Response {
        self.request(Method::GET, None)
    }

    pub fn set(&self, data: &str) -> Response {
        self.request(Method::PUT, Some(data))
    }

    pub fn push(&self, data: &str) -> Response {
        self.request(Method::POST, Some(data))
    }

    pub fn update(&self, data: &str) -> Response {
        self.request(Method::PATCH, Some(data))
    }

    pub fn delete(&self) -> Response {
        self.request(Method::DELETE, None)
    }

    fn request(&self, method: Method, data: Option<&str>) -> Response {
        let url: &str = &self.base_uri;
        let mut handler = http::handle();

        let req = match method {
            Method::GET     => handler.get(url),
            Method::POST    => handler.post(url, data.unwrap()),
            Method::PUT     => handler.put(url, data.unwrap()),
            Method::PATCH   => handler.patch(url, data.unwrap()),
            Method::DELETE  => handler.delete(url)
        };
        let res = req.exec().unwrap();

        let body = match str::from_utf8(res.get_body()) {
            Ok(b) => b,
            Err(..) => "Unable to parse"
        };

        return Response {
            body: body.to_string(),
            code: res.get_code(),
        };
    }
}

enum Method {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
}

pub struct Response {
    pub body: String,
    pub code: u32,
}

impl Response {
    pub fn is_success(&self) -> bool {
        if self.code < 400 {
            return true;
        }
        return false;
    }
}
<commit_msg>More rust style<commit_after>extern crate curl;

use std::str;
use curl::http;

mod util;

pub struct Firebase {
    base_uri: String,
}

impl Firebase {
    pub fn new(base_uri: &str) -> Self {
        Firebase {
            base_uri: base_uri.to_string(),
        }
    }

    pub fn authenticated(base_uri: &str, auth_token: &str) -> Self {
        let uri = util::trim_right(base_uri, "/");
        Firebase {
            base_uri: format!("{}&auth={}", uri, auth_token)
        }
    }

    pub fn at(&self, path: &str) -> Self {
        let mut components = self.base_uri.split('&');

        let base = components.next().unwrap();
        let base = util::trim_right(base, ".json");
        let path = util::add_right(path, ".json");
        let url  = util::join(base, &path, "/");

        let url = if let Some(args) = components.next() {
            url + "&" + args
        } else {
            url
        };

        Firebase {
            base_uri: url
        }
    }

    pub fn get(&self) -> Response {
        self.request(Method::GET, None)
    }

    pub fn set(&self, data: &str) -> Response {
        self.request(Method::PUT, Some(data))
    }

    pub fn push(&self, data: &str) -> Response {
        self.request(Method::POST, Some(data))
    }

    pub fn update(&self, data: &str) -> Response {
        self.request(Method::PATCH, Some(data))
    }

    pub fn delete(&self) -> Response {
        self.request(Method::DELETE, None)
    }

    fn request(&self, method: Method, data: Option<&str>) -> Response {
        let url: &str = &self.base_uri;
        let mut handler = http::handle();

        let req = match method {
            Method::GET     => handler.get(url),
            Method::POST    => handler.post(url, data.unwrap()),
            Method::PUT     => handler.put(url, data.unwrap()),
            Method::PATCH   => handler.patch(url, data.unwrap()),
            Method::DELETE  => handler.delete(url)
        };
        let res = req.exec().unwrap();

        let body = match str::from_utf8(res.get_body()) {
            Ok(b) => b,
            Err(..) => "Unable to parse"
        };

        Response {
            body: body.to_string(),
            code: res.get_code(),
        }
    }
}

enum Method {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
}

pub struct Response {
    pub body: String,
    pub code: u32,
}

impl Response {
    pub fn is_success(&self) -> bool {
        if self.code < 400 {
            return true;
        }
        return false;
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! An implementation of the [Roughtime](https://roughtime.googlesource.com/roughtime)
//! secure time synchronization protocol.
//!
//! Roughtime aims to achieve rough time synchronisation in a secure way that doesn't
//! depend on any particular time server, and in such a way that, if a time server does
//! misbehave, clients end up with cryptographic proof of it.
//!
//! # Protocol
//!
//! Roughtime messages are represetned by [`RtMessage`](struct.RtMessage.html) which
//! implements the mapping of Roughtime `u32` [`tags`](enum.Tag.html) to byte-strings.
//!
//! # Server
//!
//! A Roughtime server implementation is in `src/bin/server.rs`. The server is
//! configured via a yaml file:
//!
//! ```yaml
//! interface: 127.0.0.1
//! port: 8686
//! seed: f61075c988feb9cb700a4a6a3291bfbc9cab11b9c9eca8c802468eb38a43d7d3
//! ```
//!
//! Where:
//!
//!   * **interface** - IP address or interface name for listening to client requests
//!   * **port** - UDP port to listen to requests
//!   * **seed** - A 32-byte hexadecimal value used as the seed to generate the
//!                server's long-term key pair. **This is a secret value**, treat it
//!                with care.
//!
//! To run the server:
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```
//!

extern crate byteorder;

mod error;
mod tag;
mod message;

pub mod sign;

pub use error::Error;
pub use tag::Tag;
pub use message::RtMessage;

/// Version of Roughenough
pub const VERSION: &str = "0.3.1";

//  Constants and magic numbers of the Roughtime protocol

/// Minimum size (in bytes) of a client request
pub const MIN_REQUEST_LENGTH: u32 = 1024;

/// Minimum size (in bytes) of seeds used to derive private keys
pub const MIN_SEED_LENGTH: u32 = 32;

/// Size (in bytes) of an Ed25519 public key
pub const PUBKEY_LENGTH: u32 = 32;

/// Size (in bytes) of the client's nonce
pub const NONCE_LENGTH: u32 = 64;

/// Size (in bytes) of an Ed25519 signature
pub const SIGNATURE_LENGTH: u32 = 64;

/// Size (in bytes) of server's timestamp value
pub const TIMESTAMP_LENGTH: u32 = 8;

/// Size (in bytes) of server's time uncertainty value
pub const RADIUS_LENGTH: u32 = 4;

/// Prefixed to the server's certificate before generating or verifying certificate's signature
pub const CERTIFICATE_CONTEXT: &str = "RoughTime v1 delegation signature--\x00";

/// Prefixed to the server's response before generating or verifying the server's signature
pub const SIGNED_RESPONSE_CONTEXT: &str = "RoughTime v1 response signature\x00";

/// Value prepended to leaves prior to hashing
pub const TREE_LEAF_TWEAK: &[u8] = &[0x00];

/// Value prepended to nodes prior to hashing
pub const TREE_NODE_TWEAK: &[u8] = &[0x01];
<commit_msg>Update docs to include client<commit_after>// Copyright 2017 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! An implementation of the [Roughtime](https://roughtime.googlesource.com/roughtime)
//! secure time synchronization protocol.
//!
//! Roughtime aims to achieve rough time synchronisation in a secure way that doesn't
//! depend on any particular time server, and in such a way that, if a time server does
//! misbehave, clients end up with cryptographic proof of it.
//!
//! # Protocol
//!
//! Roughtime messages are represetned by [`RtMessage`](struct.RtMessage.html) which
//! implements the mapping of Roughtime `u32` [`tags`](enum.Tag.html) to byte-strings.
//!
//! # Client
//!
//! A Roughtime client can be found in `src/bin/client.rs`. To run the client:
//!
//! ```bash
//! $ cargo run --release --bin client roughtime.int08h.com 2002
//! ```
//!
//! Consult the client's `--help` output for all runtime options.
//!
//! # Server
//!
//! A Roughtime server implementation is in `src/bin/server.rs`. The server is
//! configured via a yaml file:
//!
//! ```yaml
//! interface: 127.0.0.1
//! port: 8686
//! seed: f61075c988feb9cb700a4a6a3291bfbc9cab11b9c9eca8c802468eb38a43d7d3
//! ```
//!
//! Where:
//!
//!   * **interface** - IP address or interface name for listening to client requests
//!   * **port** - UDP port to listen to requests
//!   * **seed** - A 32-byte hexadecimal value used as the seed to generate the
//!                server's long-term key pair. **This is a secret value**, treat it
//!                with care.
//!
//! To run the server:
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```
//!

extern crate byteorder;

mod error;
mod tag;
mod message;

pub mod sign;

pub use error::Error;
pub use tag::Tag;
pub use message::RtMessage;

/// Version of Roughenough
pub const VERSION: &str = "0.3.1";

//  Constants and magic numbers of the Roughtime protocol

/// Minimum size (in bytes) of a client request
pub const MIN_REQUEST_LENGTH: u32 = 1024;

/// Minimum size (in bytes) of seeds used to derive private keys
pub const MIN_SEED_LENGTH: u32 = 32;

/// Size (in bytes) of an Ed25519 public key
pub const PUBKEY_LENGTH: u32 = 32;

/// Size (in bytes) of the client's nonce
pub const NONCE_LENGTH: u32 = 64;

/// Size (in bytes) of an Ed25519 signature
pub const SIGNATURE_LENGTH: u32 = 64;

/// Size (in bytes) of server's timestamp value
pub const TIMESTAMP_LENGTH: u32 = 8;

/// Size (in bytes) of server's time uncertainty value
pub const RADIUS_LENGTH: u32 = 4;

/// Prefixed to the server's certificate before generating or verifying certificate's signature
pub const CERTIFICATE_CONTEXT: &str = "RoughTime v1 delegation signature--\x00";

/// Prefixed to the server's response before generating or verifying the server's signature
pub const SIGNED_RESPONSE_CONTEXT: &str = "RoughTime v1 response signature\x00";

/// Value prepended to leaves prior to hashing
pub const TREE_LEAF_TWEAK: &[u8] = &[0x00];

/// Value prepended to nodes prior to hashing
pub const TREE_NODE_TWEAK: &[u8] = &[0x01];
<|endoftext|>


<commit_before>//! A crate that implements [editorconfig](http://editorconfig.org/).
extern crate regex;

extern crate ordermap;

mod ini;
use regex::{Regex, Captures};

use ordermap::OrderMap;

use std::path::{Path, PathBuf};
use std::error::Error;

/// Finds all possible `conffile`s starting from `path` until root.
fn crawl_paths(path: &Path, conffile: &str) -> Result<Vec<PathBuf>, Box<Error>> {
    let mut path = path.canonicalize()?;
    let mut result = vec![];
    while path.parent().is_some() {
        let mut adjacent_file = path.clone();
        adjacent_file.set_file_name(conffile);
        path.pop();
        if !adjacent_file.exists() {
            continue;
        }
        result.push(adjacent_file);
    }
    return Ok(result);
}

fn glob_match(pattern: &String, candidate: &String) -> bool {
    // Step 1. Escape the crap out of the existing pattern
    // println!("B: {}", pattern);
    let pattern = pattern.replace(".", r"\.");
    let unmatched_open_bracket_regex = Regex::new(r"\[([^\]]*)$").unwrap();
    let pattern = unmatched_open_bracket_regex.replace(&pattern, r"\[$1")
        .to_string();
    // Step 2. Convert sh globs to regexes
    // Handling * and ** is weird but this actually works
    let pattern = pattern.replace("*", "[^/]*");
    let pattern = pattern.replace("[^/]*[^/]*", ".*");
    let pattern = pattern.replace("?", ".");
    let pattern = pattern.replace("[!", "[^");
    let alternation_regex = Regex::new(r"\{(.*,.*)\}").unwrap();
    let pattern = alternation_regex.replace(&pattern, |caps: &Captures| {
            let padded_cases = format!(",{},", &caps[1]);
            let quantifier = if padded_cases.contains(",,") { "?" } else { "" };
            let cases = caps[1].replace(",", "|");
            format!("({}){}", cases, quantifier)
        })
        .to_string();
    let pattern = pattern.replace("{", r"\{");
    let pattern = pattern.replace("}", r"\}");
    let pattern = pattern.replace("||", "|");
    let pattern = pattern.replace("(|", "(");
    let pattern = pattern.replace("|)", ")");
    let mut pattern = pattern;
    pattern.push('$');
    // println!("A: {}", pattern);
    // Step 3. Actually do the testing
    let final_regex = Regex::new(&pattern).unwrap();
    return final_regex.is_match(candidate);
}

fn parse_config(target: &Path, conf_file: &Path) -> Result<OrderMap<String, String>, Box<Error>> {
    let ini_data = ini::Ini::load_from_file(conf_file)?;
    let mut result = OrderMap::new();
    if let Some(general) = ini_data.section::<String>(None) {
        if let Some(root) = general.get("root") {
            if root.to_lowercase() == "true" {
                result.insert("root".to_string(), "true".to_string());
            }
        }
    }
    let target = target.as_os_str().to_os_string().into_string().unwrap();
    #[cfg(windows)]
    let target = target.replace("\\", "/");
    for (label, data) in ini_data.iter() {
        if let Some(ref label) = *label {
            if label.len() > 4096 {
                continue;
            }
            if glob_match(label, &target) {
                for (k, v) in data.iter() {
                    result.insert(k.clone(), v.clone());
                }
            }
        }
    }

    // Preprocessing may or may not actually be part of the spec
    // so I'm stealing this from editorconfig-core-py
    if let Some(indent_style) = result.clone().get("indent_style") {
        if indent_style == "tab" {
            if result.get("indent_size").is_none() {
                result.insert("indent_size".to_string(), "tab".to_string());
            }
        }
    }
    if let Some(indent_size) = result.clone().get("indent_size") {
        if indent_size != "tab" {
            if result.get("tab_width").is_none() {
                result.insert("tab_width".to_string(), indent_size.clone());
            }
        } else {
            if let Some(tab_width) = result.clone().get("tab_width") {
                result.insert("indent_size".to_string(), tab_width.clone());
            }
        }
    }
    Ok(result)
}

fn is_known_key(key: &str) -> bool {
    let known_keys = ["indent_style",
                      "indent_size",
                      "tab_width",
                      "end_of_line",
                      "charset",
                      "trim_trailing_whitespace",
                      "insert_final_newline"];
    known_keys.contains(&key)
}

/// Finds the configuration that applies to the file passed in `file_path`.
///
/// The `file_path` argument is the path to a file.
///
/// It looks for a file named `.editorconfig` in the file's directory and in every parent directory.
/// A search for `.editorconfig` files will stop if root (`/`) is reached or an `.editorconfig` file with `root=true` is found.
///
/// # Example
/// ```
/// use std::path::Path;
///
/// let res = editorconfig::get_config(Path::new("./test_files/simple/file.txt")).unwrap();
/// for (k, v) in res.iter() {
///     println!("{}={}", *k, *v);
/// }
/// ```
/// # Errors
///  It returns an error:
///
/// - when the `.editorconfig` file can't be found
///
/// - when it can't parse it
///
/// - when the `file_path` is malformed (check `std::fs::canonicalize` docs) or is a directory.
///
pub fn get_config(file_path: &Path) -> Result<OrderMap<String, String>, Box<Error>> {
    get_config_conffile(file_path, ".editorconfig")
}

/// Finds actual configuration that applies to file with given path.
/// # MAINLY USED FOR TESTING AND INTERNAL USE, CHECK `get_config`.
///
/// Looks for config data in given filename; in normal operation this will be ".editorconfig".
pub fn get_config_conffile(file_path: &Path,
                           conffile: &str)
                           -> Result<OrderMap<String, String>, Box<Error>> {
    let paths = crawl_paths(file_path, conffile)?;
    if paths.is_empty() {
        return Err(Box::new(std::io::Error::from(std::io::ErrorKind::NotFound)));
    }
    let mut result = OrderMap::new();
    for conf_path in paths {
        let options = parse_config(file_path, &conf_path)?;
        for (k, v) in options.iter() {
            let k = k.to_lowercase();
            let v = if is_known_key(&k) {
                v.to_lowercase()
            } else {
                v.clone()
            };
            if k.len() > 50 || v.len() > 255 {
                continue;
            }
            if !result.contains_key(&k) && k != "root" {
                result.insert(k, v);
            }
        }
        if let Some(root) = options.get("root") {
            if root.to_lowercase() == "true" {
                break;
            }
        }
    }
    return Ok(result);
}

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

    #[test]
    fn works_with_multi_level_directories() {
        let cfg = get_config(Path::new("./test_files/multi_level/foo/bar/file.txt")).unwrap();
        let mut map = OrderMap::new();
        map.insert("end_of_line".to_owned(), "lf".to_owned());
        map.insert("insert_final_newline".to_owned(), "true".to_owned());
        assert_eq!(cfg, map);
    }

    #[test]
    #[should_panic]
    fn get_editorconfig_for_non_existing_file() {
        assert!(get_config(Path::new("./test_files/diocano")).is_ok());
    }
}
<commit_msg>Fix tests, again<commit_after>//! A crate that implements [editorconfig](http://editorconfig.org/).
extern crate regex;

extern crate ordermap;

mod ini;
use regex::{Regex, Captures};

use ordermap::OrderMap;

use std::path::{Path, PathBuf};
use std::error::Error;

/// Finds all possible `conffile`s starting from `path` until root.
fn crawl_paths(path: &Path, conffile: &str) -> Result<Vec<PathBuf>, Box<Error>> {
    let mut path = if path.exists() {
        path.canonicalize()?
    } else {
        path.to_path_buf()
    };

    let mut result = vec![];
    while path.parent().is_some() {
        let mut adjacent_file = path.clone();
        adjacent_file.set_file_name(conffile);
        path.pop();
        if !adjacent_file.exists() {
            continue;
        }
        result.push(adjacent_file);
    }
    return Ok(result);
}

fn glob_match(pattern: &String, candidate: &String) -> bool {
    // Step 1. Escape the crap out of the existing pattern
    // println!("B: {}", pattern);
    let pattern = pattern.replace(".", r"\.");
    let unmatched_open_bracket_regex = Regex::new(r"\[([^\]]*)$").unwrap();
    let pattern = unmatched_open_bracket_regex.replace(&pattern, r"\[$1")
        .to_string();
    // Step 2. Convert sh globs to regexes
    // Handling * and ** is weird but this actually works
    let pattern = pattern.replace("*", "[^/]*");
    let pattern = pattern.replace("[^/]*[^/]*", ".*");
    let pattern = pattern.replace("?", ".");
    let pattern = pattern.replace("[!", "[^");
    let alternation_regex = Regex::new(r"\{(.*,.*)\}").unwrap();
    let pattern = alternation_regex.replace(&pattern, |caps: &Captures| {
            let padded_cases = format!(",{},", &caps[1]);
            let quantifier = if padded_cases.contains(",,") { "?" } else { "" };
            let cases = caps[1].replace(",", "|");
            format!("({}){}", cases, quantifier)
        })
        .to_string();
    let pattern = pattern.replace("{", r"\{");
    let pattern = pattern.replace("}", r"\}");
    let pattern = pattern.replace("||", "|");
    let pattern = pattern.replace("(|", "(");
    let pattern = pattern.replace("|)", ")");
    let mut pattern = pattern;
    pattern.push('$');
    // println!("A: {}", pattern);
    // Step 3. Actually do the testing
    let final_regex = Regex::new(&pattern).unwrap();
    return final_regex.is_match(candidate);
}

fn parse_config(target: &Path, conf_file: &Path) -> Result<OrderMap<String, String>, Box<Error>> {
    let ini_data = ini::Ini::load_from_file(conf_file)?;
    let mut result = OrderMap::new();
    if let Some(general) = ini_data.section::<String>(None) {
        if let Some(root) = general.get("root") {
            if root.to_lowercase() == "true" {
                result.insert("root".to_string(), "true".to_string());
            }
        }
    }
    let target = target.as_os_str().to_os_string().into_string().unwrap();
    #[cfg(windows)]
    let target = target.replace("\\", "/");
    for (label, data) in ini_data.iter() {
        if let Some(ref label) = *label {
            if label.len() > 4096 {
                continue;
            }
            if glob_match(label, &target) {
                for (k, v) in data.iter() {
                    result.insert(k.clone(), v.clone());
                }
            }
        }
    }

    // Preprocessing may or may not actually be part of the spec
    // so I'm stealing this from editorconfig-core-py
    if let Some(indent_style) = result.clone().get("indent_style") {
        if indent_style == "tab" {
            if result.get("indent_size").is_none() {
                result.insert("indent_size".to_string(), "tab".to_string());
            }
        }
    }
    if let Some(indent_size) = result.clone().get("indent_size") {
        if indent_size != "tab" {
            if result.get("tab_width").is_none() {
                result.insert("tab_width".to_string(), indent_size.clone());
            }
        } else {
            if let Some(tab_width) = result.clone().get("tab_width") {
                result.insert("indent_size".to_string(), tab_width.clone());
            }
        }
    }
    Ok(result)
}

fn is_known_key(key: &str) -> bool {
    let known_keys = ["indent_style",
                      "indent_size",
                      "tab_width",
                      "end_of_line",
                      "charset",
                      "trim_trailing_whitespace",
                      "insert_final_newline"];
    known_keys.contains(&key)
}

/// Finds the configuration that applies to the file passed in `file_path`.
///
/// The `file_path` argument is the path to a file.
///
/// It looks for a file named `.editorconfig` in the file's directory and in every parent directory.
/// A search for `.editorconfig` files will stop if root (`/`) is reached or an `.editorconfig` file with `root=true` is found.
///
/// # Example
/// ```
/// use std::path::Path;
///
/// let res = editorconfig::get_config(Path::new("./test_files/simple/file.txt")).unwrap();
/// for (k, v) in res.iter() {
///     println!("{}={}", *k, *v);
/// }
/// ```
/// # Errors
///  It returns an error:
///
/// - when the `.editorconfig` file can't be found
///
/// - when it can't parse it
///
/// - when the `file_path` is malformed (check `std::fs::canonicalize` docs) or is a directory.
///
pub fn get_config(file_path: &Path) -> Result<OrderMap<String, String>, Box<Error>> {
    get_config_conffile(file_path, ".editorconfig")
}

/// Finds actual configuration that applies to file with given path.
/// # MAINLY USED FOR TESTING AND INTERNAL USE, CHECK `get_config`.
///
/// Looks for config data in given filename; in normal operation this will be ".editorconfig".
pub fn get_config_conffile(file_path: &Path,
                           conffile: &str)
                           -> Result<OrderMap<String, String>, Box<Error>> {
    let paths = crawl_paths(file_path, conffile)?;

    let mut result = OrderMap::new();
    for conf_path in paths {
        let options = parse_config(file_path, &conf_path)?;
        for (k, v) in options.iter() {
            let k = k.to_lowercase();
            let v = if is_known_key(&k) {
                v.to_lowercase()
            } else {
                v.clone()
            };
            if k.len() > 50 || v.len() > 255 {
                continue;
            }
            if !result.contains_key(&k) && k != "root" {
                result.insert(k, v);
            }
        }
        if let Some(root) = options.get("root") {
            if root.to_lowercase() == "true" {
                break;
            }
        }
    }
    return Ok(result);
}

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

    #[test]
    fn works_with_multi_level_directories() {
        let cfg = get_config(Path::new("./test_files/multi_level/foo/bar/file.txt")).unwrap();
        let mut map = OrderMap::new();
        map.insert("end_of_line".to_owned(), "lf".to_owned());
        map.insert("insert_final_newline".to_owned(), "true".to_owned());
        assert_eq!(cfg, map);
    }

    #[test]
    fn get_editorconfig_for_non_existing_file() {
        assert!(get_config(Path::new("./test_files/diocano")).is_ok());
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use ffi::{FcPattern, FcObjectSet, FcFontSet};

use std::c_str::CString;
use std::mem;

mod ffi;

struct Pattern {
    pat: *mut FcPattern,
    strings: Vec<CString>,
}

impl Pattern {
    fn add_string(&mut self, name: &str, val: &str) {
        let c_name = name.to_c_str();
        let c_val = val.to_c_str();

        unsafe { ffi::FcPatternAddString(self.pat, c_name.as_ptr(), c_val.as_ptr() as *const u8); }

        self.strings.push_all(&[c_name, c_val]);
    }

    unsafe fn to_pattern(&self) -> *mut FcPattern {
        self.pat
    }
}

impl Drop for Pattern {
    fn drop(&mut self) {
        unsafe { ffi::FcPatternDestroy(self.pat); }
    }
}

struct Properties {
    vec: Vec<CString>,
}

impl Properties {
    pub fn new() -> Properties {
        Properties { vec: Vec::new() }
    }

    fn add(&mut self, prop: &str) {
        self.vec.push(prop.to_c_str());
    }

    unsafe fn to_object_set(&self) -> *mut FcObjectSet {
        let object_set = ffi::FcObjectSetCreate();

        for c_str in self.vec.iter() {
            assert_eq!(ffi::FcObjectSetAdd(object_set, c_str.as_ptr()), 1);
        }

        object_set
    }
}

struct FontSet {
    fonts: *mut FcFontSet,
}

impl FontSet {

    unsafe fn with_pattern_args(pat: *mut FcPattern, args: *mut FcObjectSet) -> FontSet {
        FontSet { fonts: ffi::FcFontList(mem::transmute(0u), pat, args) }
    }

}

impl Drop for FcFontSet {
    fn drop(&mut self) {
        // Transmute shouldn't be necessary but somehow is, otherwise:
        // error: mismatched types: expected `*mut ffi::Struct__FcFontSet`,
        // found `*mut *mut ffi::Struct__FcPattern`
        // (expected struct ffi::Struct__FcFontSet, found *-ptr)
        unsafe { ffi::FcFontSetDestroy(mem::transmute(self.fonts)); }
    }
}

#[test]
fn it_works() {
    let result = unsafe { ffi::FcInit() };

    assert_eq!(result, 1);
}

#[test]
fn test_props() {
    let mut props = Properties::new();
    props.add("family");
    props.add("file");

}

<commit_msg>Implement basic font search<commit_after>//! A wrapper around freedesktop's `fontconfig` utility, for locating fontfiles on a
//! Linux-based system. Requires `libfontconfig` to be installed.
//!
//! Use `Font` for a high-level search by family name and optional style (e.g. "FreeSerif"
//! and "italic"), and `Pattern` for a more in-depth search.
//!
//! See the [fontconfig developer reference][1] for more information.
//!
//! [1]: http://www.freedesktop.org/software/fontconfig/fontconfig-devel/t1.html

#![feature(phase, unsafe_destructor)]

extern crate libc;
#[phase(plugin, link)] extern crate log;

use ffi::FcPattern;

use std::c_str::CString;
use std::kinds::marker;
use std::mem;
use std::ptr;
use std::sync::{Once, ONCE_INIT};

mod ffi;

static FC_INIT: Once = ONCE_INIT;

fn fc_init() {
    FC_INIT.doit(|| assert_eq!(unsafe { ffi::FcInit() }, 1));
}

/// A very high-level view of a font, only concerned with the name and its file location.
///
/// ##Example
/// ```rust
/// let font = Font::find("freeserif", Some("italic")).unwrap();
/// println!("Name: {}\nPath: {}", font.name, font.path.display());
/// ```
#[allow(dead_code)]
pub struct Font {
    /// The true name of this font
    pub name: String,
    /// The location of this font on the filesystem.
    pub path: Path,
}

impl Font {
    /// Find a font of the given `family` (e.g. Dejavu Sans, FreeSerif),
    /// optionally filtering by `style`. Both fields are case-insensitive.
    pub fn find(family: &str, style: Option<&str>) -> Option<Font> {
        let mut pat = Pattern::new();
        pat.add_string("family", family);

        if let Some(style) = style {
            pat.add_string("style", style);
        }

        let font_match = pat.font_match();

        font_match.name().and_then(|name| font_match.filename().map(|filename|
            Font {
                name: name.into_string(),
                path: Path::new(filename),
            }
        ))
    }

    #[allow(dead_code)]
    fn print_debug(&self) {
        debug!("Name: {}\nPath: {}", self.name, self.path.display());
    }
}

/// A safe wrapper around fontconfig's `FcPattern`.
pub struct Pattern<'a> {
    _m: marker::ContravariantLifetime<'a>,
    pat: *mut FcPattern,
    /// This is just to hold the RAII C-strings while the `FcPattern` is alive.
    strings: Vec<CString>,
}

impl<'a> Pattern<'a> {
    pub fn new() -> Pattern<'a> {
        fc_init();

        Pattern {
            _m: marker::ContravariantLifetime,
            pat: unsafe{ ffi::FcPatternCreate() },
            strings: Vec::new(),
        }
    }

    fn from_pattern(pat: *mut FcPattern) -> Pattern<'a> {
        unsafe { ffi::FcPatternReference(pat); }

        Pattern {
            _m: marker::ContravariantLifetime,
            pat: pat,
            strings: Vec::new(),
        }
    }

    /// Add a key-value pair to this pattern.
    ///
    /// See useful keys in the [fontconfig reference][1].
    ///
    /// [1]: http://www.freedesktop.org/software/fontconfig/fontconfig-devel/x19.html
    pub fn add_string(&mut self, name: &str, val: &str) {
        let c_name = name.to_c_str();

        // `val` is copied inside fontconfig so no need to allocate it again.
        val.with_c_str(|c_str| unsafe {
            ffi::FcPatternAddString(self.pat, c_name.as_ptr(), c_str as *const u8);
        });

        self.strings.push(c_name);
    }

    /// Get the value for a key from this pattern.
    pub fn get_string<'a>(&'a self, name: &str) -> Option<&'a str> {
        name.with_c_str(|c_str| unsafe {
            let ret = mem::uninitialized();
            if ffi::FcPatternGetString(&*self.pat, c_str, 0, ret) == 0 {
                Some(std::str::from_c_str(*ret as *const i8))
            } else { None }
        })
    }

    /// Print this pattern to stdout with all its values.
    #[allow(dead_code)]
    pub fn print(&self) {
        unsafe { ffi::FcPatternPrint(&*self.pat); }
    }

    fn default_substitute(&mut self) {
        unsafe { ffi::FcDefaultSubstitute(self.pat); }
    }

    fn config_substitute(&mut self) {
        unsafe { ffi::FcConfigSubstitute(ptr::null_mut(), self.pat, ffi::FcMatchPattern); }
    }

    /// Get the best available match for this pattern, returned as a new pattern.
    pub fn font_match<'a>(&'a mut self) -> Pattern<'a> {
        self.default_substitute();
        self.config_substitute();

        unsafe {
            let mut res = ffi::FcResultNoMatch;
            Pattern::from_pattern(
                ffi::FcFontMatch(ptr::null_mut(), self.pat, &mut res)
            )
        }
    }

    /// Get the "fullname" (human-readable name) of this pattern.
    pub fn name(&self) -> Option<&str> {
        self.get_string("fullname")
    }

    /// Get the "file" (path on the filesystem) of this font pattern.
    pub fn filename(&self) -> Option<&str> {
        self.get_string("file")
    }
}

#[unsafe_destructor]
impl<'a> Drop for Pattern<'a> {
    fn drop(&mut self) {
        unsafe { ffi::FcPatternDestroy(self.pat); }
    }
}

#[test]
fn it_works() {
    fc_init();
}

#[test]
fn test_find_font() {
    Font::find("dejavu sans", None).unwrap().print_debug();
    Font::find("dejavu sans", Some("oblique")).unwrap().print_debug();
}

<|endoftext|>


<commit_before>use std::collections::BTreeMap;

pub mod error;
use self::error::Error;

extern crate time;

extern crate ansi_term;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan};

pub mod api_result;
//use api_result::Body;

extern crate rustc_serialize;
use rustc_serialize::json::{self, ToJson, Json};

fn main() {
    println!("--- {} ---", Red
        //.blink()
        .bold().paint("Test error Model").to_string());

    let code    = Error::get_code(&Error::Success);
    let message = Error::get_message(&Error::Success);
    println!("{{\"code\": {},\"message\":{:?}}}", code, message);

    println!("--- END ---");

    println!("\n--- {} ---", Green.bold().paint("Time").to_string());
    let time_now = time::now();
    println!("{:?}", time_now);

    let time = time::get_time();
    println!("{:?}", time);

    let time_str = time::strftime("%Y-%m-%d %H:%M:%S", &time_now);
    println!("{:?}", time_str);
    println!("--- END ---");

    println!("\n--- {} ---", Yellow.bold().paint("JSON encode decode").to_string());
    let json_str = "{\"code\":0,\"message\":\"OK\",\"data\":{\"keyword\":\"Rust, api, php, nginx\"},\"ip\":[\"192.168.0.168\",\"127.0.0.1\"]}";
    println!("json_str: {}", Blue.paint(json_str.to_string()));
    //let json: api_result::Body = json::decode(&json_str).unwrap();
    let mut obj: BTreeMap<String, json::Json> = BTreeMap::new();
    obj.insert("os".to_string(), json::Json::from_str("{\"page\": 11, \"os\": \"Linux, Unix, MacOS\"}").unwrap());
    obj.insert("test".to_string(), json::Json::from_str("[\"just test\"]").unwrap());
    let json_obj = api_result::Body {
        code: code,
        message: message.to_string(),
        data: obj,
    };
    let encode_str = json_obj.to_json();
    println!("encode_str: {}", encode_str.to_string());
    println!("--- END ---");

    println!("\n--- {} ---", Purple.bold().paint("BTreeMap".to_string()));
    // BTreeMap 的 key 只能是同一种类型
    let mut map   = BTreeMap::new();
    let mut n_map = BTreeMap::new();
    n_map.insert(0, "Hi, world");
    n_map.insert(1, "a");
    n_map.insert(2, "b");
    map.insert("key", "value");
    map.insert("os", "linux terminal");
    let n_keys: Vec<_>      = n_map.keys().cloned().collect();
    let n_values: Vec<&str> = n_map.values().cloned().collect();
    let keys: Vec<&str>   = map.keys().cloned().collect();
    let values: Vec<&str> = map.values().cloned().collect();
    println!("n_map->keys:   {:?}", n_keys);
    println!("n_map->values: {:?}", n_values);
    println!("map->keys:   {:?}", keys);
    println!("map->values: {:?}", values);
    println!("--- END ---");
}
<commit_msg>加入 map 迭代; json decode 的异常处理.<commit_after>use std::collections::BTreeMap;

pub mod error;
use self::error::Error;

extern crate time;

extern crate ansi_term;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan};

pub mod api_result;
//use api_result::Body;

extern crate rustc_serialize;
use rustc_serialize::json::{self, ToJson, Json};

fn main() {
    println!("--- {} ---", Red
        //.blink()
        .bold().paint("Test error Model").to_string());

    let code    = Error::get_code(&Error::Success);
    let message = Error::get_message(&Error::Success);
    println!("{{\"code\": {},\"message\":{:?}}}", code, message);

    println!("--- END ---");

    println!("\n--- {} ---", Green.bold().paint("Time").to_string());
    let time_now = time::now();
    println!("{:?}", time_now);

    let time = time::get_time();
    println!("{:?}", time);

    let time_str = time::strftime("%Y-%m-%d %H:%M:%S", &time_now);
    println!("{:?}", time_str);
    println!("--- END ---");

    println!("\n--- {} ---", Yellow.bold().paint("JSON encode decode").to_string());
    let json_str = "{\"code\":0,\"message\":\"OK\",\"data\":{\"keyword\":\"Rust, api, php, nginx\"},\"ip\":[\"192.168.0.168\",\"127.0.0.1\"]}";
    println!("json_str: {}", Blue.paint(json_str.to_string()));
    //let json: api_result::Body = json::decode(&json_str).unwrap();
    let mut obj: BTreeMap<String, json::Json> = BTreeMap::new();
    obj.insert("os".to_string(), json::Json::from_str("{\"page\": 11, \"os\": \"Linux, Unix, MacOS\"}").unwrap_or_else(|e| { panic!("failed to execute process: {}", e) }));
    obj.insert("test".to_string(), json::Json::from_str("[\"just test\"]").unwrap_or_else(|e| { panic!("failed to execute process: {}", e) }));
    let json_obj = api_result::Body {
        code: code,
        message: message.to_string(),
        data: obj,
    };
    let encode_str = json_obj.to_json();
    println!("encode_str: {}", encode_str.to_string());
    println!("--- END ---");

    println!("\n--- {} ---", Purple.bold().paint("BTreeMap".to_string()));
    // BTreeMap 的 key 只能是同一种类型
    let mut map   = BTreeMap::new();
    let mut n_map = BTreeMap::new();
    n_map.insert(0, "Hi, world");
    n_map.insert(1, "a");
    n_map.insert(2, "b");
    map.insert("key", "value");
    map.insert("os", "linux terminal");
    let n_keys: Vec<_>      = n_map.keys().cloned().collect();
    let n_values: Vec<&str> = n_map.values().cloned().collect();
    let keys: Vec<&str>   = map.keys().cloned().collect();
    let values: Vec<&str> = map.values().cloned().collect();
    println!("n_map->keys:   {:?}", n_keys);
    println!("n_map->values: {:?}", n_values);
    println!("map->keys:   {:?}", keys);
    println!("map->values: {:?}", values);
    for (k, v) in map.iter() {
        println!("map.{} = {}", k, v);
    }
    println!("--- END ---");
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

pub mod error;
use self::error::Error;

extern crate time;

extern crate ansi_term;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan};

pub mod api_result;
//use api_result::Body;

extern crate rustc_serialize;
use rustc_serialize::json::{self, ToJson, Json};

fn main() {
    println!("--- {} ---", Red
        //.blink()
        .bold().paint("Test error Model").to_string());

    let code    = Error::get_code(&Error::Success);
    let message = Error::get_message(&Error::Success);
    println!("{{\"code\": {},\"message\":{:?}}}", code, message);

    println!("--- END ---");

    println!("\n--- {} ---", Green.bold().paint("Time").to_string());
    let time_now = time::now();
    println!("{:?}", time_now);

    let time = time::get_time();
    println!("{:?}", time);

    let time_str = time::strftime("%Y-%m-%d %H:%M:%S", &time_now);
    println!("{:?}", time_str);
    println!("--- END ---");

    println!("\n--- {} ---", Yellow.bold().paint("JSON encode decode").to_string());
    let json_str = "{\"code\":0,\"message\":\"OK\",\"data\":{\"keyword\":\"Rust, api, php, nginx\"},\"ip\":[\"192.168.0.168\",\"127.0.0.1\"]}";
    println!("json_str: {}", Blue.paint(json_str.to_string()));
    //let json: api_result::Body = json::decode(&json_str).unwrap();
    let mut obj = BTreeMap::new();
    obj.insert("os".to_string(), "linux".to_string());
    obj.insert("test".to_string(), "array".to_string());
    let json_obj = api_result::Body {
        code: code,
        message: message.to_string(),
        data: obj,
    };
    let encode_str = json_obj.to_json();
    println!("encode_str: {}", encode_str.to_string());
    println!("--- END ---");
}
<commit_msg>add BTreeMap example.<commit_after>use std::collections::BTreeMap;

pub mod error;
use self::error::Error;

extern crate time;

extern crate ansi_term;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan};

pub mod api_result;
//use api_result::Body;

extern crate rustc_serialize;
use rustc_serialize::json::{self, ToJson, Json};

fn main() {
    println!("--- {} ---", Red
        //.blink()
        .bold().paint("Test error Model").to_string());

    let code    = Error::get_code(&Error::Success);
    let message = Error::get_message(&Error::Success);
    println!("{{\"code\": {},\"message\":{:?}}}", code, message);

    println!("--- END ---");

    println!("\n--- {} ---", Green.bold().paint("Time").to_string());
    let time_now = time::now();
    println!("{:?}", time_now);

    let time = time::get_time();
    println!("{:?}", time);

    let time_str = time::strftime("%Y-%m-%d %H:%M:%S", &time_now);
    println!("{:?}", time_str);
    println!("--- END ---");

    println!("\n--- {} ---", Yellow.bold().paint("JSON encode decode").to_string());
    let json_str = "{\"code\":0,\"message\":\"OK\",\"data\":{\"keyword\":\"Rust, api, php, nginx\"},\"ip\":[\"192.168.0.168\",\"127.0.0.1\"]}";
    println!("json_str: {}", Blue.paint(json_str.to_string()));
    //let json: api_result::Body = json::decode(&json_str).unwrap();
    let mut obj = BTreeMap::new();
    obj.insert("os".to_string(), "linux".to_string());
    obj.insert("test".to_string(), "array".to_string());
    let json_obj = api_result::Body {
        code: code,
        message: message.to_string(),
        data: obj,
    };
    let encode_str = json_obj.to_json();
    println!("encode_str: {}", encode_str.to_string());
    println!("--- END ---");

    println!("\n--- {} ---", Purple.bold().paint("BTreeMap".to_string()));
    // BTreeMap 的 key 只能是同一种类型
    let mut map   = BTreeMap::new();
    let mut n_map = BTreeMap::new();
    n_map.insert(0, "Hi, world");
    n_map.insert(1, "a");
    n_map.insert(2, "b");
    map.insert("key", "value");
    map.insert("os", "linux terminal");
    let n_keys: Vec<_>      = n_map.keys().cloned().collect();
    let n_values: Vec<&str> = n_map.values().cloned().collect();
    let keys: Vec<&str>   = map.keys().cloned().collect();
    let values: Vec<&str> = map.values().cloned().collect();
    println!("n_map->keys:   {:?}", n_keys);
    println!("n_map->values: {:?}", n_values);
    println!("map->keys:   {:?}", keys);
    println!("map->values: {:?}", values);
    println!("--- END ---");
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(asm)]
#![feature(box_syntax)]
#![feature(int_uint)]
#![feature(simd)]
#![feature(slicing_syntax)]

#![allow(unstable)]

extern crate "rustc-serialize" as serialize;
extern crate time;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blake2b;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod curve25519;
pub mod digest;
pub mod ed25519;
pub mod fortuna;
pub mod ghash;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod ripemd160;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod aesni;
<commit_msg>Remove #![feature(int_uint)] since all uses of ints and uints have been removed<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(asm)]
#![feature(box_syntax)]
#![feature(simd)]
#![feature(slicing_syntax)]

#![allow(unstable)]

extern crate "rustc-serialize" as serialize;
extern crate time;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blake2b;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod curve25519;
pub mod digest;
pub mod ed25519;
pub mod fortuna;
pub mod ghash;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod ripemd160;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod aesni;
<|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/.

//! A library for interacting with Twitter.
//!
//! [Repository](https://github.com/QuietMisdreavus/twitter-rs)
//!
//! egg-mode is a Twitter library that aims to make as few assumptions about the user's codebase as
//! possible. Endpoints are exposed as bare functions where authentication details are passed in as
//! arguments, rather than as builder functions of a root "service" manager. The only exceptions to
//! this guideline are endpoints with many optional parameters, like posting a status update or
//! updating the metadata of a list.
//!
//! To use the Twitter API, there are some extra steps you need to do, both inside and outside of
//! your app code. Find the Authentication Overview and quick start guide in the [Token][]
//! documentation. The following examples already have a `token` on hand.
//!
//! [Token]: enum.Token.html
//!
//! To load the profile information of a single user:
//!
//! ```rust,no_run
//! # let token = egg_mode::Token::Access {
//! #     consumer: egg_mode::KeyPair::new("", ""),
//! #     access: egg_mode::KeyPair::new("", ""),
//! # };
//! let rustlang = egg_mode::user::show("rustlang", &token).unwrap();
//!
//! println!("{} (@{})", rustlang.name, rustlang.screen_name);
//! ```
//!
//! To post a new tweet:
//!
//! ```rust,no_run
//! # let token = egg_mode::Token::Access {
//! #     consumer: egg_mode::KeyPair::new("", ""),
//! #     access: egg_mode::KeyPair::new("", ""),
//! # };
//! use egg_mode::tweet::DraftTweet;
//!
//! let post = DraftTweet::new("Hey Twitter!").send(&token).unwrap();
//! ```
//!
//! # Types and Functions
//!
//! All of the main content of egg-mode is in submodules, but there are a few things here in the
//! crate root. To wit, it contains items related to authentication and a couple items that all the
//! submodules use.
//!
//! ## `Response<T>`
//!
//! Every method that calls Twitter and carries rate-limit information wraps its return value in a
//! [`Response`][] struct, that transmits this information to your app. From there, you can handle
//! the rate-limit information to hold off on that kind of request, or simply grab its `response`
//! field to get the output of whatever method you called. `Response` also implements `Deref`, so
//! for the most part you can access fields of the final result without having to grab the
//! `response` field directly.
//!
//! `Response` also has IntoIterator implementations and iterator creation methods that echo those
//! on `Vec<T>`, for methods that return Vecs. These methods and iterator types distribute the
//! rate-limit information across each iteration.
//!
//! There's also a type alias, [`WebResponse`], which is an alias to `Result<Response<T>, Error>`,
//! indicating a shorthand for network calls that return rate-limit metadata.
//!
//! [`Response`]: struct.Response.html
//! [`WebResponse`]: type.WebResponse.html
//!
//! ## Authentication Types/Functions
//!
//! The remaining types and methods are explained as part of the [authentication overview][Token],
//! with the exception of `verify_tokens`, which is a simple method to ensure a given token is
//! still valid.
//!
//! # Modules
//!
//! As there are many actions available in the Twitter API, egg-mode divides them roughly into
//! several modules by their shared purpose. Here's a sort of high-level overview, in rough order
//! from "most important" to "less directly used":
//!
//! ## Primary actions
//!
//! These could be considered the "core" actions within the Twitter API that egg-mode has made
//! available.
//!
//! * `tweet`: This module lets you act on tweets. Here you can find actions to load a user's
//!   timeline, post a new tweet, or like and retweet individual posts.
//! * `user`: This module lets you act on users, be it by following or unfollowing them, loading
//!   their profile information, blocking or muting them, or showing the relationship between two
//!   users.
//! * `search`: Due to the complexity of searching for tweets, it gets its own module.
//! * `direct`: Here you can work with a user's Direct Messages, either by loading DMs they've sent
//!   or received, or by sending new ones.
//! * `list`: This module lets you act on lists, from creating and deleting them, adding and
//!   removing users, or loading the posts made by their members.
//! * `text`: Text processing functions to count characters in new tweets and extract links and
//!   hashtags for highlighting and linking.
//!
//! ## Secondary actions
//!
//! These modules still contain direct actions for Twitter, but they can be considered as having
//! more of a helper role than something you might use directly.
//!
//! * `place`: Here are actions that look up physical locations that can be attached to tweets, as
//!   well at the `Place` struct that appears on tweets with locations attached.
//! * `service`: These are some miscellaneous methods that show information about the Twitter
//!   service as a whole, like loading the maximum length of t.co URLs or loading the current Terms
//!   of Service or Privacy Policy.
//!
//! ## Helper structs
//!
//! These modules contain some implementations that wrap some pattern seen in multiple "action"
//! modules.
//!
//! * `cursor`: This contains a helper trait and some helper structs that allow effective cursoring
//!   through certain collections of results from Twitter.
//! * `entities`: Whenever some text can be returned that may contain links, hashtags, media, or
//!   user mentions, its metadata is parsed into something that lives in this module.
//! * `error`: Any interaction with Twitter may result in an error condition, be it from finding a
//!   tweet or user that doesn't exist or the network connection being unavailable. All the error
//!   types are aggregated into an enum in this module.

#![warn(missing_docs)]
#![warn(unused_extern_crates)]
#![warn(unused_qualifications)]

#[macro_use] extern crate hyper;
#[macro_use] extern crate lazy_static;
extern crate futures;
extern crate tokio_core;
extern crate hyper_tls;
extern crate native_tls;
extern crate url;
extern crate rand;
extern crate hmac;
extern crate sha_1;
extern crate rustc_serialize;
extern crate mime;
extern crate chrono;
extern crate regex;
extern crate unicode_normalization;

#[macro_use] mod common;
mod auth;
pub mod error;
pub mod user;
pub mod entities;
pub mod cursor;
pub mod tweet;
pub mod search;
pub mod place;
pub mod direct;
pub mod service;
pub mod text;
pub mod list;
mod links;

pub use auth::{KeyPair, Token, AuthFuture, request_token, authorize_url, authenticate_url,
               access_token, verify_tokens, bearer_token, invalidate_bearer};
pub use common::{Response, ResponseIter, ResponseIterRef,
                 ResponseIterMut, FutureResponse, TwitterFuture};
<commit_msg>update crate-root docs<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/.

//! A library for interacting with Twitter.
//!
//! [Repository](https://github.com/QuietMisdreavus/twitter-rs)
//!
//! egg-mode is a Twitter library that aims to make as few assumptions about the user's codebase as
//! possible. Endpoints are exposed as bare functions where authentication details are passed in as
//! arguments, rather than as builder functions of a root "service" manager. The only exceptions to
//! this guideline are endpoints with many optional parameters, like posting a status update or
//! updating the metadata of a list.
//!
//! To use the Twitter API, there are some extra steps you need to do, both inside and outside of
//! your app code. Find the Authentication Overview and quick start guide in the [Token][]
//! documentation. The following examples already have a `token` on hand. In addition, using
//! asynchronous network calls, the various methods of this library assume the presence of a
//! [tokio][] `Core` whose `Handle` you pass to any given call. These are also assumed to be
//! present in each example.
//!
//! [Token]: enum.Token.html
//! [tokio]: https://tokio.rs
//!
//! To load the profile information of a single user:
//!
//! ```rust,no_run
//! # extern crate egg_mode; extern crate tokio_core;
//! # use egg_mode::Token; use tokio_core::reactor::{Core, Handle};
//! # fn main() {
//! # let (token, mut core, handle): (Token, Core, Handle) = unimplemented!();
//! let rustlang = core.run(egg_mode::user::show("rustlang", &token, &handle)).unwrap();
//!
//! println!("{} (@{})", rustlang.name, rustlang.screen_name);
//! # }
//! ```
//!
//! To post a new tweet:
//!
//! ```rust,no_run
//! # extern crate egg_mode; extern crate tokio_core;
//! # use egg_mode::Token; use tokio_core::reactor::{Core, Handle};
//! use egg_mode::tweet::DraftTweet;
//! # fn main() {
//! # let (token, mut core, handle): (Token, Core, Handle) = unimplemented!();
//!
//! let post = core.run(DraftTweet::new("Hey Twitter!").send(&token, &handle)).unwrap();
//! # }
//! ```
//!
//! # Types and Functions
//!
//! All of the main content of egg-mode is in submodules, but there are a few things here in the
//! crate root. To wit, it contains items related to authentication and a couple items that all the
//! submodules use.
//!
//! ## `Response<T>`
//!
//! Every method that calls Twitter and carries rate-limit information wraps its return value in a
//! [`Response`][] struct, that transmits this information to your app. From there, you can handle
//! the rate-limit information to hold off on that kind of request, or simply grab its `response`
//! field to get the output of whatever method you called. `Response` also implements `Deref`, so
//! for the most part you can access fields of the final result without having to grab the
//! `response` field directly.
//!
//! `Response` also has IntoIterator implementations and iterator creation methods that echo those
//! on `Vec<T>`, for methods that return Vecs. These methods and iterator types distribute the
//! rate-limit information across each iteration.
//!
//! [`Response`]: struct.Response.html
//!
//! ## `TwitterFuture<'a, T>`
//!
//! Any method that requires a network call will return a handle to the pending network call, in
//! most cases the type [`TwitterFuture`][]. This type (and any other `*Future` in this library)
//! implements the `Future` trait, for use as an asynchronous network call. All `Future`
//! implementations in this library use the `Error` enum as their Error value. For more information
//! on how to use the `Future` trait, check out the [Tokio documentation guides][].
//!
//! In addition, there is also a `FutureResponse` type alias, that corresponds to
//! `TwitterFuture<'a, Response<T>>`, for methods that return rate-limit information.
//!
//! [`TwitterFuture`]: struct.TwitterFuture.html
//! [Tokio documentation guides]: https://tokio.rs/docs/getting-started/tokio/
//!
//! ## Authentication Types/Functions
//!
//! The remaining types and methods are explained as part of the [authentication overview][Token],
//! with the exception of `verify_tokens`, which is a simple method to ensure a given token is
//! still valid.
//!
//! # Modules
//!
//! As there are many actions available in the Twitter API, egg-mode divides them roughly into
//! several modules by their shared purpose. Here's a sort of high-level overview, in rough order
//! from "most important" to "less directly used":
//!
//! ## Primary actions
//!
//! These could be considered the "core" actions within the Twitter API that egg-mode has made
//! available.
//!
//! * `tweet`: This module lets you act on tweets. Here you can find actions to load a user's
//!   timeline, post a new tweet, or like and retweet individual posts.
//! * `user`: This module lets you act on users, be it by following or unfollowing them, loading
//!   their profile information, blocking or muting them, or showing the relationship between two
//!   users.
//! * `search`: Due to the complexity of searching for tweets, it gets its own module.
//! * `direct`: Here you can work with a user's Direct Messages, either by loading DMs they've sent
//!   or received, or by sending new ones.
//! * `list`: This module lets you act on lists, from creating and deleting them, adding and
//!   removing users, or loading the posts made by their members.
//! * `text`: Text processing functions to count characters in new tweets and extract links and
//!   hashtags for highlighting and linking.
//!
//! ## Secondary actions
//!
//! These modules still contain direct actions for Twitter, but they can be considered as having
//! more of a helper role than something you might use directly.
//!
//! * `place`: Here are actions that look up physical locations that can be attached to tweets, as
//!   well at the `Place` struct that appears on tweets with locations attached.
//! * `service`: These are some miscellaneous methods that show information about the Twitter
//!   service as a whole, like loading the maximum length of t.co URLs or loading the current Terms
//!   of Service or Privacy Policy.
//!
//! ## Helper structs
//!
//! These modules contain some implementations that wrap some pattern seen in multiple "action"
//! modules.
//!
//! * `cursor`: This contains a helper trait and some helper structs that allow effective cursoring
//!   through certain collections of results from Twitter.
//! * `entities`: Whenever some text can be returned that may contain links, hashtags, media, or
//!   user mentions, its metadata is parsed into something that lives in this module.
//! * `error`: Any interaction with Twitter may result in an error condition, be it from finding a
//!   tweet or user that doesn't exist or the network connection being unavailable. All the error
//!   types are aggregated into an enum in this module.

#![warn(missing_docs)]
#![warn(unused_extern_crates)]
#![warn(unused_qualifications)]

#[macro_use] extern crate hyper;
#[macro_use] extern crate lazy_static;
extern crate futures;
extern crate tokio_core;
extern crate hyper_tls;
extern crate native_tls;
extern crate url;
extern crate rand;
extern crate hmac;
extern crate sha_1;
extern crate rustc_serialize;
extern crate mime;
extern crate chrono;
extern crate regex;
extern crate unicode_normalization;

#[macro_use] mod common;
mod auth;
pub mod error;
pub mod user;
pub mod entities;
pub mod cursor;
pub mod tweet;
pub mod search;
pub mod place;
pub mod direct;
pub mod service;
pub mod text;
pub mod list;
mod links;

pub use auth::{KeyPair, Token, AuthFuture, request_token, authorize_url, authenticate_url,
               access_token, verify_tokens, bearer_token, invalidate_bearer};
pub use common::{Response, ResponseIter, ResponseIterRef,
                 ResponseIterMut, FutureResponse, TwitterFuture};
<|endoftext|>


<commit_before>//! A simple, thread-safe IRC client library.
#![crate_name = "irc"]
#![crate_type = "lib"]
#![unstable]

#![feature(if_let)]
#![feature(slicing_syntax)]
extern crate serialize;

pub mod conn;
pub mod data;
pub mod server;
<commit_msg>Added license attribute to lib.rs.<commit_after>//! A simple, thread-safe IRC client library.
#![crate_name = "irc"]
#![crate_type = "lib"]
#![license = "Public Domain"]
#![unstable]

#![feature(if_let)]
#![feature(slicing_syntax)]
extern crate serialize;

pub mod conn;
pub mod data;
pub mod server;
<|endoftext|>


<commit_before>#[deny(missing_docs)]

extern crate input;
extern crate piston_window;
extern crate rustc_serialize;
extern crate viewport;

mod builder;
mod rebind;

use input::{Input, Button, Motion};
use piston_window::Size;
use std::collections::HashMap;
use std::default::Default;
use viewport::Viewport;

pub use rebind::InputRebind;
pub use builder::InputTranslatorBuilder;

/// Represents a logical action to be bound to a particular button press, e.g.
/// jump, attack, or move forward
pub trait Action: Copy + PartialEq + Eq { }

/// A translated action.
#[derive(Debug, Copy, Clone)]
pub enum Translated<A: Action> {
    /// A keypress event which was bound to an action
    Press(A),

    /// A key release event which was bound to an action
    Release(A),

    /// A translated mouse motion. The logical origin of a translated MouseCursor event
    /// is in the top left corner of the window, and the logical scroll is non-natural.
    /// Relative events are unchanged for now.
    Move(Motion)
}

/// An object which translates piston::input::Input events into input_map::Translated<A> events
#[derive(Clone)]
pub struct InputTranslator<A: Action> {
    keymap: KeyMap<A>,
    mouse_translator: MouseTranslator
}

impl<A: Action> InputTranslator<A> {

    /// Creates an empty InputTranslator.
    pub fn new(size: Size) -> Self {
        InputTranslator {
            keymap: KeyMap::new(),
            mouse_translator: MouseTranslator::new(size)
        }
    }

    /// Translate an Input into a Translated<A> event
    pub fn translate(&self, input: &Input) -> Option<Translated<A>> {
        macro_rules! translate_button(($but_state:ident, $but_var:ident) => (
            match self.keymap.translate($but_var) {
                Some(act) => Some(Translated::$but_state(act)),
                None => None
            });
        );

        match input {
            &Input::Press(button) => translate_button!(Press, button),
            &Input::Release(button) => translate_button!(Release, button),
            &Input::Move(motion) =>
                Some(Translated::Move(self.mouse_translator.translate(motion))),
            _ => None
        }
    }

    pub fn add_binding(&mut self, but: Button, act: A) {
        self.keymap.add_mapping(but, act);
    }

    /// Re-set the mouse bounds size used for calculating mouse events
    pub fn set_size(&mut self, size: Size) {
        self.mouse_translator.viewport_size = size
    }

    /// Re-set the mouse bounds size from a viewport
    pub fn set_size_from_viewport(&mut self, vp: Viewport) {
        self.set_size(Size::from(vp.draw_size));
    }
}

#[derive(Clone)]
struct MouseTranslator {
    pub x_axis_motion_inverted: bool,
    pub y_axis_motion_inverted: bool,
    pub x_axis_scroll_inverted: bool,
    pub y_axis_scroll_inverted: bool,
    pub viewport_size: Size
}

impl MouseTranslator {
    fn new(size: Size) -> Self {
        MouseTranslator {
            x_axis_motion_inverted: false,
            y_axis_motion_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            viewport_size: size
        }
    }

    fn translate(&self, motion: Motion) -> Motion {
        match motion {
            Motion::MouseCursor(x, y) => {
                let (sw, sh) = {
                    let Size {width, height} = self.viewport_size;
                    (width as f64, height as f64)
                };

                let cx = if self.x_axis_motion_inverted { sw - x } else { x };
                let cy = if self.y_axis_motion_inverted { sh - y } else { y };

                Motion::MouseCursor(cx, cy)
            },
            Motion::MouseScroll(x, y) => {
                let mx = if self.x_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                let my = if self.y_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                Motion::MouseScroll(x * mx, y * my)
            },
            relative => relative
        }
    }
}

#[derive(Clone, Debug)]
struct KeyMap<A: Action> {
    btn_map: HashMap<ButtonTuple, A>
}

impl<A: Action> KeyMap<A> {
    fn new() -> Self {
        KeyMap {
            btn_map: HashMap::new()
        }
    }

    fn add_mapping(&mut self, button: Button, action: A) {
        let mut bt = self.get_bindings_for_action(action).unwrap_or(ButtonTuple::new());
        let bt = if bt.insert_inplace(button) {bt} else {ButtonTuple::new()};
        self.btn_map.insert(bt, action);
    }

    fn get_bindings_for_action(&self, action: A) -> Option<ButtonTuple> {
        self.btn_map.iter().find(|&(_, &a)| a == action).map(|(&bt, _)| bt)
    }

    #[allow(dead_code)]
    fn get_ref_bindings_for_action(&self, action: A) -> Option<&ButtonTuple> {
        self.btn_map.iter().find(|&(_, &a)| a == action).map(|(bt, _)| bt)
    }

    #[cfg(unimplemented)] // This gives a compile error
    fn get_ref_bindings_for_action_mut(&mut self, action: A) -> Option<&mut ButtonTuple> {
        self.btn_map.iter_mut().find(|&(_, &mut a)| a == action).as_mut().map(|&mut (bt, _)| bt)
    }

    fn translate(&self, button: Button) -> Option<A> {
        self.btn_map.iter().find(|&(&bt, _)| bt.contains(button)).map(|(_, &a)| a)
    }
}

/// A three-element tuple of Option<Button>. Used as the key of an InputTranslator
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ButtonTuple(pub Option<Button>, pub Option<Button>, pub Option<Button>);

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

    fn contains(&self, btn: Button) -> bool {
        let sbtn = Some(btn);
        self.0 == sbtn || self.1 == sbtn || self.2 == sbtn
    }

    #[allow(dead_code)]
    fn remove_inplace(&mut self, btn: Button) {
        let sbtn = Some(btn);
        if self.0 == sbtn {self.0 = None}
        if self.1 == sbtn {self.1 = None}
        if self.2 == sbtn {self.2 = None}
    }

    #[allow(dead_code)]
    fn replace_inplace(&mut self, btn_idx: u32, btn: Button) -> bool {
        match btn_idx {
            0 => {self.0 = Some(btn); true},
            1 => {self.1 = Some(btn); true},
            2 => {self.2 = Some(btn); true},
            _ => false
        }
    }

    fn insert_inplace(&mut self, btn: Button) -> bool {
        match self {
            &mut ButtonTuple(a, b, c) if a.is_none() => {*self = ButtonTuple(Some(btn), b, c); true},
            &mut ButtonTuple(a, b, c) if b.is_none() => {*self = ButtonTuple(a, Some(btn), c); true},
            &mut ButtonTuple(a, b, c) if c.is_none() => {*self = ButtonTuple(a, b, Some(btn)); true}
            _ => false
        }
    }
}

impl Default for ButtonTuple {
    fn default() -> Self { ButtonTuple(None, None, None) }
}
<commit_msg>Action now requires Hash<commit_after>#[deny(missing_docs)]

extern crate input;
extern crate piston_window;
extern crate rustc_serialize;
extern crate viewport;

mod builder;
mod rebind;

use input::{Input, Button, Motion};
use piston_window::Size;
use std::collections::HashMap;
use std::default::Default;
use std::hash::Hash;
use viewport::Viewport;

pub use rebind::InputRebind;
pub use builder::InputTranslatorBuilder;

/// Represents a logical action to be bound to a particular button press, e.g.
/// jump, attack, or move forward
pub trait Action: Copy + PartialEq + Eq + Hash { }

/// A translated action.
#[derive(Debug, Copy, Clone)]
pub enum Translated<A: Action> {
    /// A keypress event which was bound to an action
    Press(A),

    /// A key release event which was bound to an action
    Release(A),

    /// A translated mouse motion. The logical origin of a translated MouseCursor event
    /// is in the top left corner of the window, and the logical scroll is non-natural.
    /// Relative events are unchanged for now.
    Move(Motion)
}

/// An object which translates piston::input::Input events into input_map::Translated<A> events
#[derive(Clone)]
pub struct InputTranslator<A: Action> {
    keymap: KeyMap<A>,
    mouse_translator: MouseTranslator
}

impl<A: Action> InputTranslator<A> {

    /// Creates an empty InputTranslator.
    pub fn new(size: Size) -> Self {
        InputTranslator {
            keymap: KeyMap::new(),
            mouse_translator: MouseTranslator::new(size)
        }
    }

    /// Translate an Input into a Translated<A> event
    pub fn translate(&self, input: &Input) -> Option<Translated<A>> {
        macro_rules! translate_button(($but_state:ident, $but_var:ident) => (
            match self.keymap.translate($but_var) {
                Some(act) => Some(Translated::$but_state(act)),
                None => None
            });
        );

        match input {
            &Input::Press(button) => translate_button!(Press, button),
            &Input::Release(button) => translate_button!(Release, button),
            &Input::Move(motion) =>
                Some(Translated::Move(self.mouse_translator.translate(motion))),
            _ => None
        }
    }

    pub fn add_binding(&mut self, but: Button, act: A) {
        self.keymap.add_mapping(but, act);
    }

    /// Re-set the mouse bounds size used for calculating mouse events
    pub fn set_size(&mut self, size: Size) {
        self.mouse_translator.viewport_size = size
    }

    /// Re-set the mouse bounds size from a viewport
    pub fn set_size_from_viewport(&mut self, vp: Viewport) {
        self.set_size(Size::from(vp.draw_size));
    }
}

#[derive(Clone)]
struct MouseTranslator {
    pub x_axis_motion_inverted: bool,
    pub y_axis_motion_inverted: bool,
    pub x_axis_scroll_inverted: bool,
    pub y_axis_scroll_inverted: bool,
    pub viewport_size: Size
}

impl MouseTranslator {
    fn new(size: Size) -> Self {
        MouseTranslator {
            x_axis_motion_inverted: false,
            y_axis_motion_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            viewport_size: size
        }
    }

    fn translate(&self, motion: Motion) -> Motion {
        match motion {
            Motion::MouseCursor(x, y) => {
                let (sw, sh) = {
                    let Size {width, height} = self.viewport_size;
                    (width as f64, height as f64)
                };

                let cx = if self.x_axis_motion_inverted { sw - x } else { x };
                let cy = if self.y_axis_motion_inverted { sh - y } else { y };

                Motion::MouseCursor(cx, cy)
            },
            Motion::MouseScroll(x, y) => {
                let mx = if self.x_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                let my = if self.y_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                Motion::MouseScroll(x * mx, y * my)
            },
            relative => relative
        }
    }
}

#[derive(Clone, Debug)]
struct KeyMap<A: Action> {
    btn_map: HashMap<ButtonTuple, A>
}

impl<A: Action> KeyMap<A> {
    fn new() -> Self {
        KeyMap {
            btn_map: HashMap::new()
        }
    }

    fn add_mapping(&mut self, button: Button, action: A) {
        let mut bt = self.get_bindings_for_action(action).unwrap_or(ButtonTuple::new());
        let bt = if bt.insert_inplace(button) {bt} else {ButtonTuple::new()};
        self.btn_map.insert(bt, action);
    }

    fn get_bindings_for_action(&self, action: A) -> Option<ButtonTuple> {
        self.btn_map.iter().find(|&(_, &a)| a == action).map(|(&bt, _)| bt)
    }

    #[allow(dead_code)]
    fn get_ref_bindings_for_action(&self, action: A) -> Option<&ButtonTuple> {
        self.btn_map.iter().find(|&(_, &a)| a == action).map(|(bt, _)| bt)
    }

    #[cfg(unimplemented)] // This gives a compile error
    fn get_ref_bindings_for_action_mut(&mut self, action: A) -> Option<&mut ButtonTuple> {
        self.btn_map.iter_mut().find(|&(_, &mut a)| a == action).as_mut().map(|&mut (bt, _)| bt)
    }

    fn translate(&self, button: Button) -> Option<A> {
        self.btn_map.iter().find(|&(&bt, _)| bt.contains(button)).map(|(_, &a)| a)
    }
}

/// A three-element tuple of Option<Button>. Used as the key of an InputTranslator
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ButtonTuple(pub Option<Button>, pub Option<Button>, pub Option<Button>);

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

    fn contains(&self, btn: Button) -> bool {
        let sbtn = Some(btn);
        self.0 == sbtn || self.1 == sbtn || self.2 == sbtn
    }

    #[allow(dead_code)]
    fn remove_inplace(&mut self, btn: Button) {
        let sbtn = Some(btn);
        if self.0 == sbtn {self.0 = None}
        if self.1 == sbtn {self.1 = None}
        if self.2 == sbtn {self.2 = None}
    }

    #[allow(dead_code)]
    fn replace_inplace(&mut self, btn_idx: u32, btn: Button) -> bool {
        match btn_idx {
            0 => {self.0 = Some(btn); true},
            1 => {self.1 = Some(btn); true},
            2 => {self.2 = Some(btn); true},
            _ => false
        }
    }

    fn insert_inplace(&mut self, btn: Button) -> bool {
        match self {
            &mut ButtonTuple(a, b, c) if a.is_none() => {*self = ButtonTuple(Some(btn), b, c); true},
            &mut ButtonTuple(a, b, c) if b.is_none() => {*self = ButtonTuple(a, Some(btn), c); true},
            &mut ButtonTuple(a, b, c) if c.is_none() => {*self = ButtonTuple(a, b, Some(btn)); true}
            _ => false
        }
    }
}

impl Default for ButtonTuple {
    fn default() -> Self { ButtonTuple(None, None, None) }
}
<|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 async_trait::async_trait;
use futures_core::stream::Stream;

pub struct DatasetName(String);
pub struct BlankNode(u64);
pub struct IRI(String);
pub struct DefaultGraph {}
pub struct LangTag(String);
pub struct LangLiteral { pub value: String, pub lang_tag: LangTag }
pub struct UnknownLiteral { pub value: String, pub r#type: IRI }

pub enum Literal {
  LangLiteral(LangLiteral),
  StringLiteral(String),
  BooleanLiteral(bool),
  LongLiteral(i64),
  DoubleLiteral(f64),
  UnknownLiteral(UnknownLiteral)
}

pub enum Range {
  LangLiteralRange { start: LangLiteral, stop: LangLiteral },
  StringLiteralRange { start: String, stop: String },
  LongLiteralRange { start: i64, stop: i64 },
  DoubleLiteralRange { start: f64, stop: f64 }
}

pub enum Subject {
  IRI(IRI),
  BlankNode(BlankNode),
  DefaultGraph(DefaultGraph)
}

pub enum Predicate {
  IRI(IRI)
}

pub enum Object {
  Subject(Subject),
  Literal(Literal)
}

pub enum Graph {
  IRI(IRI),
  BlankNode(BlankNode),
  DefaultGraph(DefaultGraph)
}

pub struct Statement { pub subject: Subject, pub predicate: Predicate, pub object: Object }
pub struct PersistedStatement { pub dataset: DatasetName, pub statement: Statement, pub graph: Graph }

//val a: IRI = IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").getOrElse(???)
//fn validLangTag(langTag: String) -> Boolean =
//  "[a-zA-Z]+(-[a-zA-Z0-9]+)*".r.matches(langTag)

pub struct LigatureError(String);

#[async_trait]
pub trait Ligature {
  fn all_datasets(&self) -> Box<dyn Stream<Item = DatasetName>>;
  fn match_datasets(&self, prefix: String) -> Box<dyn Stream<Item = DatasetName>>;
  fn match_datasets_range(&self, from: String, to: String) -> Box<dyn Stream<Item = DatasetName>>;
  async fn create_dataset(&self, dataset: DatasetName) -> Result<DatasetName, LigatureError>;
  async fn delete_dataset(&self, dataset: DatasetName) -> Result<DatasetName, LigatureError>;
  async fn query(&self, dataset: DatasetName) -> Result<Box<dyn QueryTx>, LigatureError>;
  async fn write(&self, dataset: DatasetName) -> Result<Box<dyn WriteTx>, LigatureError>;
}

pub trait QueryTx {
  fn all_statements(&self) -> Box<dyn Stream<Item = PersistedStatement>>;
  fn match_statements(&self,
                      subject: Option<Subject>,
                      predicate: Option<Predicate>,
                      object: Option<Object>,
                      graph: Option<Graph>) -> Box<dyn Stream<Item = PersistedStatement>>;
  fn match_statements_range(&self,
                      subject: Option<Subject>,
                      predicate: Option<Predicate>,
                      graph: Option<Graph>,
                      range: Range) -> Box<dyn Stream<Item = PersistedStatement>>;
}

#[async_trait]
pub trait WriteTx {
  async fn new_blank_node(&self) -> Result<BlankNode, LigatureError>;
  async fn add_statement(&self, statement: Statement, graph: Graph) -> Result<PersistedStatement, LigatureError>;
  async fn remove_statement(&self, statement: Statement, graph: Graph) -> Result<Statement, LigatureError>;
  async fn cancel(&self) -> Result<(), LigatureError>;
}

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

    #[test]
    fn valid_dataset_names() {
//   assert(!validNamedNode(NamedNode("")))
//   assert(validNamedNode(NamedNode("http://localhost/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost(/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost{/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost\\/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost</people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost>/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost[/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost]/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost\"/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost'/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost`/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost\t/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost\n/people/7")))
//   assert(!validNamedNode(NamedNode("http://localhost /people/7")))
//   assert(validNamedNode(NamedNode("hello")))
//   assert(validNamedNode(NamedNode("_:")))
//   assert(validNamedNode(NamedNode("_:valid")))
//   assert(validNamedNode(NamedNode("_:1")))
//   assert(validNamedNode(NamedNode("_:1344")))
    }

    #[test]
    fn valid_lang_tags() {
      // assert(!validLangTag(""))
      // assert(validLangTag("en"))
      // assert(!validLangTag("en-"))
      // assert(validLangTag("en-fr"))
      // assert(!validLangTag("en-fr-"))
      // assert(validLangTag("en-fr-sp"))
      // assert(validLangTag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"))
      // assert(!validLangTag("en-fr-ef "))
    }
}
<commit_msg>rustfmt<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 async_trait::async_trait;
use futures_core::stream::Stream;

pub struct DatasetName(String);
pub struct BlankNode(u64);
pub struct IRI(String);
pub struct DefaultGraph {}
pub struct LangTag(String);
pub struct LangLiteral {
    pub value: String,
    pub lang_tag: LangTag,
}
pub struct UnknownLiteral {
    pub value: String,
    pub r#type: IRI,
}

pub enum Literal {
    LangLiteral(LangLiteral),
    StringLiteral(String),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64),
    UnknownLiteral(UnknownLiteral),
}

pub enum Range {
    LangLiteralRange {
        start: LangLiteral,
        stop: LangLiteral,
    },
    StringLiteralRange {
        start: String,
        stop: String,
    },
    LongLiteralRange {
        start: i64,
        stop: i64,
    },
    DoubleLiteralRange {
        start: f64,
        stop: f64,
    },
}

pub enum Subject {
    IRI(IRI),
    BlankNode(BlankNode),
    DefaultGraph(DefaultGraph),
}

pub enum Predicate {
    IRI(IRI),
}

pub enum Object {
    Subject(Subject),
    Literal(Literal),
}

pub enum Graph {
    IRI(IRI),
    BlankNode(BlankNode),
    DefaultGraph(DefaultGraph),
}

pub struct Statement {
    pub subject: Subject,
    pub predicate: Predicate,
    pub object: Object,
}
pub struct PersistedStatement {
    pub dataset: DatasetName,
    pub statement: Statement,
    pub graph: Graph,
}

//val a: IRI = IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").getOrElse(???)
//fn validLangTag(langTag: String) -> Boolean =
//  "[a-zA-Z]+(-[a-zA-Z0-9]+)*".r.matches(langTag)

pub struct LigatureError(String);

#[async_trait]
pub trait Ligature {
    fn all_datasets(&self) -> Box<dyn Stream<Item = DatasetName>>;
    fn match_datasets(&self, prefix: String) -> Box<dyn Stream<Item = DatasetName>>;
    fn match_datasets_range(&self, from: String, to: String)
        -> Box<dyn Stream<Item = DatasetName>>;
    async fn create_dataset(&self, dataset: DatasetName) -> Result<DatasetName, LigatureError>;
    async fn delete_dataset(&self, dataset: DatasetName) -> Result<DatasetName, LigatureError>;
    async fn query(&self, dataset: DatasetName) -> Result<Box<dyn QueryTx>, LigatureError>;
    async fn write(&self, dataset: DatasetName) -> Result<Box<dyn WriteTx>, LigatureError>;
}

pub trait QueryTx {
    fn all_statements(&self) -> Box<dyn Stream<Item = PersistedStatement>>;
    fn match_statements(
        &self,
        subject: Option<Subject>,
        predicate: Option<Predicate>,
        object: Option<Object>,
        graph: Option<Graph>,
    ) -> Box<dyn Stream<Item = PersistedStatement>>;
    fn match_statements_range(
        &self,
        subject: Option<Subject>,
        predicate: Option<Predicate>,
        graph: Option<Graph>,
        range: Range,
    ) -> Box<dyn Stream<Item = PersistedStatement>>;
}

#[async_trait]
pub trait WriteTx {
    async fn new_blank_node(&self) -> Result<BlankNode, LigatureError>;
    async fn add_statement(
        &self,
        statement: Statement,
        graph: Graph,
    ) -> Result<PersistedStatement, LigatureError>;
    async fn remove_statement(
        &self,
        statement: Statement,
        graph: Graph,
    ) -> Result<Statement, LigatureError>;
    async fn cancel(&self) -> Result<(), LigatureError>;
}

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

    #[test]
    fn valid_dataset_names() {
        //   assert(!validNamedNode(NamedNode("")))
        //   assert(validNamedNode(NamedNode("http://localhost/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost(/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost{/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost\\/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost</people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost>/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost[/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost]/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost\"/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost'/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost`/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost\t/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost\n/people/7")))
        //   assert(!validNamedNode(NamedNode("http://localhost /people/7")))
        //   assert(validNamedNode(NamedNode("hello")))
        //   assert(validNamedNode(NamedNode("_:")))
        //   assert(validNamedNode(NamedNode("_:valid")))
        //   assert(validNamedNode(NamedNode("_:1")))
        //   assert(validNamedNode(NamedNode("_:1344")))
    }

    #[test]
    fn valid_lang_tags() {
        // assert(!validLangTag(""))
        // assert(validLangTag("en"))
        // assert(!validLangTag("en-"))
        // assert(validLangTag("en-fr"))
        // assert(!validLangTag("en-fr-"))
        // assert(validLangTag("en-fr-sp"))
        // assert(validLangTag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"))
        // assert(!validLangTag("en-fr-ef "))
    }
}
<|endoftext|>


<commit_before>//! An asynchronous abstraction for discovering devices and services on a network.
//!
//! SSDP stands for Simple Service Discovery Protocol and it is a protocol that uses
//! HTTPMU to distribute messages across a local network for devices and services to
//! discover each other. SSDP can most commonly be found in devices that implement
//! `UPnP` as it is used as the discovery mechanism for that standard.

extern crate hyper;
#[macro_use]
extern crate log;
extern crate time;
#[cfg(not(windows))]
extern crate ifaces;
extern crate net2;

mod error;
mod field;
mod net;
mod receiver;

pub mod header;
pub mod message;

pub use error::{SSDPError, SSDPResult};
pub use field::FieldMap;
pub use receiver::{SSDPReceiver, SSDPIter};
<commit_msg>Add lookup_host feature<commit_after>#![allow(unused_features)]
#![feature(lookup_host)]

//! An asynchronous abstraction for discovering devices and services on a network.
//!
//! SSDP stands for Simple Service Discovery Protocol and it is a protocol that uses
//! HTTPMU to distribute messages across a local network for devices and services to
//! discover each other. SSDP can most commonly be found in devices that implement
//! `UPnP` as it is used as the discovery mechanism for that standard.

extern crate hyper;
#[macro_use]
extern crate log;
extern crate time;
#[cfg(not(windows))]
extern crate ifaces;
extern crate net2;

mod error;
mod field;
mod net;
mod receiver;

pub mod header;
pub mod message;

pub use error::{SSDPError, SSDPResult};
pub use field::FieldMap;
pub use receiver::{SSDPReceiver, SSDPIter};
<|endoftext|>


<commit_before>
pub extern crate crypto;

use crypto::digest::Digest;

pub trait Hashable {
    fn to_bytes(&self) -> &[u8];
}

impl Hashable for String {
    fn to_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

impl Hashable for str {
    fn to_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

#[derive(Clone)]
enum Tree<T> where T: Hashable + Clone {
    Leaf {
        hash: Vec<u8>,
        value: T
    },

    Node {
        hash: Vec<u8>,
        left: Box<Tree<T>>,
        right: Box<Tree<T>>
    }
}

impl <T> Tree<T> where T: Hashable + Clone {
    fn get_hash<'a>(&'a self) -> &'a Vec<u8> {
        match *self {
            Tree::Leaf { ref hash, value: _ }          => hash,
            Tree::Node { ref hash, left: _, right: _ } => hash
        }
    }
}

pub struct MerkleTree<D, T> where D: Digest + Clone, T: Hashable + Clone {
    digest: D,
    tree: Tree<T>
}

impl <T> Tree<T> where T: Hashable + Clone {

    // fn from_chunks<D>(digest: D, iter: Chunks<Tree<T>>) -> Tree<T> where D: Digest {

    // }

}

fn make_hash<D, T>(mut digest: D, bytes: &[u8]) -> Vec<u8> where D: Digest, T: Hashable + Clone {
    let mut hash = Vec::with_capacity(digest.output_bytes());
    digest.reset();
    digest.input(bytes);
    digest.result(hash.as_mut_slice());
    digest.reset();
    return hash;
}

fn combine_hashes<D>(mut digest: D, left: &[u8], right: &[u8]) -> Vec<u8> where D: Digest {
    let mut hash = Vec::with_capacity(digest.output_bytes());
    digest.reset();
    digest.input(left);
    digest.input(right);
    digest.result(hash.as_mut_slice());
    digest.reset();
    return hash;
}

fn make_leaf<D, T>(digest: D, value: T) -> Tree<T> where D: Digest + Clone, T: Hashable + Clone {
    return Tree::Leaf {
        hash: make_hash::<D, T>(digest, value.to_bytes()),
        value: value
    };
}

impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Hashable + Clone {

    // TODO: Don't clone all the things
    pub fn from_vec(digest: D, values: Vec<T>) -> MerkleTree<D, T> {
        if values.is_empty() {
            panic!("Cannot build a Merkle tree from an empty vector.");
        }

        let mut cur: Vec<_> =
            values.iter()
                  .map(|v| make_leaf::<D, T>(digest.clone(), v.clone()))
                  .collect();

        while cur.len() > 1 {
            cur = cur.chunks(2).map(|chunk|
                if chunk.len() == 1 {
                    chunk[0].clone()
                } else {
                    let left:  Tree<T> = chunk[0].clone();
                    let right: Tree<T> = chunk[1].clone();

                    let combined_hash = combine_hashes::<D>(
                        digest.clone(),
                        left.get_hash().as_slice(),
                        right.get_hash().as_slice()
                    );

                    Tree::Node {
                       hash: combined_hash,
                       left: Box::new(left),
                       right: Box::new(right)
                    }
                }
            ).collect();
        }

        return MerkleTree {
            digest: digest.clone(),
            tree: cur[0].clone()
        };

    }

}

#[cfg(test)]
use crypto::sha3::Sha3;

#[test]
fn test_stuff() {
}

#[cfg(test)]
pub mod tests;
<commit_msg>Cleanup<commit_after>
pub extern crate crypto;

use crypto::digest::Digest;

pub trait Hashable {
    fn to_bytes(&self) -> &[u8];
}

impl Hashable for String {
    fn to_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

impl Hashable for str {
    fn to_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

#[derive(Clone)]
enum Tree<T> where T: Hashable + Clone {
    Leaf {
        hash: Vec<u8>,
        value: T
    },

    Node {
        hash: Vec<u8>,
        left: Box<Tree<T>>,
        right: Box<Tree<T>>
    }
}

impl <T> Tree<T> where T: Hashable + Clone {
    fn get_hash<'a>(&'a self) -> &'a Vec<u8> {
        match *self {
            Tree::Leaf { ref hash, value: _ }          => hash,
            Tree::Node { ref hash, left: _, right: _ } => hash
        }
    }
}

pub struct MerkleTree<D, T> where D: Digest + Clone, T: Hashable + Clone {
    digest: D,
    tree: Tree<T>
}

impl <T> Tree<T> where T: Hashable + Clone {

}

fn make_hash<D, T>(mut digest: D, bytes: &[u8]) -> Vec<u8> where D: Digest {
    let mut hash = Vec::with_capacity(digest.output_bytes());
    digest.reset();
    digest.input(bytes);
    digest.result(hash.as_mut_slice());
    digest.reset();
    return hash;
}

fn combine_hashes<D>(mut digest: D, left: &[u8], right: &[u8]) -> Vec<u8> where D: Digest {
    let mut hash = Vec::with_capacity(digest.output_bytes());
    digest.reset();
    digest.input(left);
    digest.input(right);
    digest.result(hash.as_mut_slice());
    digest.reset();
    return hash;
}

fn make_leaf<D, T>(digest: D, value: T) -> Tree<T> where D: Digest, T: Hashable + Clone {
    return Tree::Leaf {
        hash: make_hash::<D, T>(digest, value.to_bytes()),
        value: value
    };
}

impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Hashable + Clone {

    // TODO: Don't clone all the things
    pub fn from_vec(digest: D, values: Vec<T>) -> MerkleTree<D, T> {
        if values.is_empty() {
            panic!("Cannot build a Merkle tree from an empty vector.");
        }

        let mut cur: Vec<_> =
            values.iter()
                  .map(|v| make_leaf::<D, T>(digest.clone(), v.clone()))
                  .collect();

        while cur.len() > 1 {
            cur = cur.chunks(2).map(|chunk|
                if chunk.len() == 1 {
                    chunk[0].clone()
                } else {
                    let left:  Tree<T> = chunk[0].clone();
                    let right: Tree<T> = chunk[1].clone();

                    let combined_hash = combine_hashes::<D>(
                        digest.clone(),
                        left.get_hash().as_slice(),
                        right.get_hash().as_slice()
                    );

                    Tree::Node {
                       hash: combined_hash,
                       left: Box::new(left),
                       right: Box::new(right)
                    }
                }
            ).collect();
        }

        return MerkleTree {
            digest: digest.clone(),
            tree: cur[0].clone()
        };

    }

}

#[cfg(test)]
use crypto::sha3::Sha3;

#[test]
fn test_stuff() {
}

#[cfg(test)]
pub mod tests;
<|endoftext|>