<commit_before>#![warn(missing_docs)]
#![doc(html_logo_url = "http://lipanski.github.io/mockito/logo/logo-black.png",
    html_root_url = "http://lipanski.github.io/mockito/generated/mockito/index.html")]

//!
//! Mockito is a library for creating HTTP mocks to be used in (integration) tests or for offline work.
//! It runs an HTTP server on your local port 1234 and can register and remove mocks.
//!
//! The server is run on a separate thread within the same process and will be cleaned up
//! at the end of the run.
//!
//! # Getting Started
//!
//! Using compiler flags, set the URL of your web client to `mockito::SERVER_URL` or `mockito::SERVER_ADDRESS`.
//!
//! # Example
//!
//! ```
//! #[cfg(test)]
//! use mockito;
//!
//! #[cfg(not(test))]
//! const URL: &'static str = "https://api.twitter.com";
//!
//! #[cfg(test)]
//! const URL: &'static str = mockito::SERVER_URL;
//! ```
//!
//! Then start mocking:
//!
//! # Example
//!
//! ```
//! #[cfg(test)]
//! mod tests {
//!   use mockito::mock;
//!
//!   #[test]
//!   fn test_something() {
//!     mock("GET", "/hello")
//!       .with_status(201)
//!       .with_header("content-type", "text/plain")
//!       .with_header("x-api-key", "1234")
//!       .with_body("world")
//!       .create();
//!
//!     // Any calls to GET /hello beyond this line will respond with 201, the
//!     // `content-type: text/plain` header and the body "world".
//!   }
//! }
//! ```
//!
//! # Run your tests
//!
//! Due to the nature of this library (all your mocks are recorded on the same server running in background),
//! it is highly recommended that you **run your tests on a single thread**:
//!
//! ```sh
//! cargo test -- --test-threads=1
//!
//! # Same, but using an environment variable
//! RUST_TEST_THREADS=1 cargo test
//! ```
//!
//! In some situations, when you're *always* testing/mocking different routes and never need to reset
//! or override the existing mocks, you might get away with running your tests on multiple threads.
//!
//! # Matching by header
//!
//! Mockito currently matches by method and path, but also by headers. The header field letter case is ignored.
//!
//! # Example
//!
//! ```
//! use mockito::mock;
//!
//! mock("GET", "/hello")
//!   .match_header("content-type", "application/json")
//!   .with_body("{'hello': 'world'}")
//!   .create();
//!
//! mock("GET", "/hello")
//!   .match_header("content-type", "text/plain")
//!   .with_body("world")
//!   .create();
//!
//! // JSON requests to GET /hello will respond with JSON, while plain requests
//! // will respond with text.
//! ```
//!
//! # Cleaning up
//!
//! Even though **mocks are matched in reverse order** (most recent one wins), in some situations
//! it might be useful to clean up right after the test. There are multiple ways of doing this.
//!
//! By using a closure:
//!
//! # Example
//!
//! ```
//! use mockito::mock;
//!
//! mock("GET", "/hello")
//!   .with_body("world")
//!   .create_for(|| {
//!     // mock only valid for the lifetime of this closure
//!     // NOTE: it might still be accessible by separate threads
//!   });
//! ```
//!
//! By calling `remove()` on the mock:
//!
//! # Example
//!
//! ```
//! use mockito::mock;
//!
//! let mut mock = mock("GET", "/hello");
//! mock.with_body("world").create();
//!
//! // do your thing
//!
//! mock.remove();
//! ```
//!
//! By calling `reset()` to **remove all mocks**:
//!
//! # Example
//!
//! ```
//! use mockito::reset;
//!
//! reset();
//! ```
//!

extern crate hyper;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate rand;

mod server;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use hyper::client::Client;
use hyper::server::Request;
use hyper::header::{Headers, ContentType, Connection};
use rand::{thread_rng, Rng};

///
/// Points to the address the mock server is running at.
/// Can be used with `std::net::TcpStream`.
///
pub const SERVER_ADDRESS: &'static str = "0.0.0.0:1234";

///
/// Points to the URL the mock server is running at.
///
pub const SERVER_URL: &'static str = "http://0.0.0.0:1234";

///
/// Initializes a mock for the provided `method` and `path`.
///
/// The mock is registered to the server only after the `create()` method has been called.
///
/// # Example
///
/// ```
/// use mockito::mock;
///
/// mock("GET", "/");
/// mock("POST", "/users");
/// mock("DELETE", "/users?id=1");
/// ```
///
pub fn mock(method: &str, path: &str) -> Mock {
    Mock::new(method, path)
}

///
/// Removes all the mocks stored on the server.
///
pub fn reset() {
    server::try_start();

    Client::new()
        .delete(&[SERVER_URL, "/mocks"].join(""))
        .send()
        .unwrap();
}

///
/// Stores information about a mocked request. Should be initialized via `mockito::mock()`.
///
#[derive(PartialEq, Debug)]
pub struct Mock {
    id: String,
    method: String,
    path: String,
    headers: HashMap<String, String>,
    response: MockResponse,
}

impl Mock {
    fn new(method: &str, path: &str) -> Self {
        Mock {
            id: thread_rng().gen_ascii_chars().take(24).collect(),
            method: method.to_owned().to_uppercase(),
            path: path.to_owned(),
            headers: HashMap::new(),
            response: MockResponse::new(),
        }
    }

    ///
    /// Allows matching a particular request header when responding with a mock.
    ///
    /// When matching a request, the field letter case is ignored.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").match_header("content-type", "application/json");
    /// ```
    ///
    /// Like most other `Mock` methods, it allows chanining:
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/")
    ///   .match_header("content-type", "application/json")
    ///   .match_header("authorization", "password");
    /// ```
    ///
    pub fn match_header(&mut self, field: &str, value: &str) -> &mut Self {
        self.headers.insert(field.to_owned(), value.to_owned());

        self
    }

    ///
    /// Sets the status code of the mock response. The default status code is 200.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_status(201);
    /// ```
    ///
    pub fn with_status(&mut self, status: usize) -> &mut Self {
        self.response.status = status;

        self
    }

    ///
    /// Sets a header of the mock response.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_header("content-type", "application/json");
    /// ```
    ///
    pub fn with_header(&mut self, field: &str, value: &str) -> &mut Self {
        self.response.headers.insert(field.to_owned(), value.to_owned());

        self
    }

    ///
    /// Sets the body of the mock response. Its `Content-Length` is handled automatically.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body("hello world");
    /// ```
    ///
    pub fn with_body(&mut self, body: &str) -> &mut Self {
        self.response.body = body.to_owned();

        self
    }

    ///
    /// Sets the body of the mock response from the contents of a file stored under `path`.
    /// Its `Content-Length` is handled automatically.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body_from_file("tests/files/simple.http");
    /// ```
    ///
    pub fn with_body_from_file(&mut self, path: &str) -> &mut Self {
        let mut file = File::open(path).unwrap();
        let mut body = String::new();

        file.read_to_string(&mut body).unwrap();

        self.response.body = body;

        self
    }

    ///
    /// Registers the mock to the server - your mock will be served only after calling this method.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body("hello world").create();
    /// ```
    ///
    pub fn create(&mut self) -> &mut Self {
        server::try_start();

        let mut headers = Headers::new();
        headers.set_raw("x-mock-id", vec!(self.id.as_bytes().to_vec()));
        headers.set_raw("x-mock-method", vec!(self.method.as_bytes().to_vec()));
        headers.set_raw("x-mock-path", vec!(self.path.as_bytes().to_vec()));

        for (field, value) in &self.headers {
            headers.set_raw("x-mock-".to_string() + field, vec!(value.as_bytes().to_vec()));
        }

        let body = serde_json::to_string(&self.response).unwrap();
        Client::new()
            .post(&[SERVER_URL, "/mocks"].join(""))
            .headers(headers)
            .header(ContentType::json())
            .header(Connection::close())
            .body(&body)
            .send()
            .unwrap();

        self
    }

    ///
    /// Registers the mock to the server, executes the passed closure and removes the mock afterwards.
    ///
    /// **NOTE:** During the closure lifetime, the mock might still be available to seperate threads.
    ///
    /// # Example
    ///
    /// ```
    /// use std::thread::{sleep};
    /// use std::time::Duration;
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body("hello world").create_for(|| {
    ///   // This mock will only be available for the next 10 seconds
    ///   sleep(Duration::new(10, 0));
    /// });
    /// ```
    ///
    pub fn create_for<F: Fn() -> ()>(&mut self, environment: F) -> &mut Self {
        self.create();
        environment();
        self.remove();

        self
    }

    ///
    /// Removes the current mock from the server.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// let mut mock = mock("GET", "/");
    /// mock.with_body("hello world").create();
    ///
    /// // stuff
    ///
    /// mock.remove();
    /// ```
    ///
    pub fn remove(&self) {
        server::try_start();

        let mut headers = Headers::new();
        headers.set_raw("x-mock-id", vec!(self.id.as_bytes().to_vec()));

        Client::new()
            .delete(&[SERVER_URL, "/mocks"].join(""))
            .headers(headers)
            .header(Connection::close())
            .send()
            .unwrap();
    }

    #[allow(missing_docs)]
    pub fn matches(&self, request: &Request) -> bool {
        self.method_matches(request)
            && self.path_matches(request)
            && self.headers_match(request)
    }

    fn method_matches(&self, request: &Request) -> bool {
        self.method == request.method.to_string().to_uppercase()
    }

    fn path_matches(&self, request: &Request) -> bool {
        self.path == request.uri.to_string()
    }

    fn headers_match(&self, request: &Request) -> bool {
        for (field, value) in self.headers.iter() {
            match request.headers.get_raw(&field) {
                Some(request_header_value) => {
                    let bytes: Vec<u8> = request_header_value.iter().flat_map(|el| el.iter().cloned()).collect();

                    if value == &String::from_utf8(bytes).unwrap() { continue }

                    return false
                },
                _ => return false
            }
        }

        true
    }
}

const DEFAULT_RESPONSE_STATUS: usize = 200;

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct MockResponse {
    status: usize,
    headers: HashMap<String, String>,
    body: String,
}

impl MockResponse {
    pub fn new() -> Self {
        MockResponse {
            status: DEFAULT_RESPONSE_STATUS,
            headers: HashMap::new(),
            body: String::new(),
        }
    }
}
<commit_msg>No need to sleep 10 seconds in the example (slows down tests)<commit_after>#![warn(missing_docs)]
#![doc(html_logo_url = "http://lipanski.github.io/mockito/logo/logo-black.png",
    html_root_url = "http://lipanski.github.io/mockito/generated/mockito/index.html")]

//!
//! Mockito is a library for creating HTTP mocks to be used in (integration) tests or for offline work.
//! It runs an HTTP server on your local port 1234 and can register and remove mocks.
//!
//! The server is run on a separate thread within the same process and will be cleaned up
//! at the end of the run.
//!
//! # Getting Started
//!
//! Using compiler flags, set the URL of your web client to `mockito::SERVER_URL` or `mockito::SERVER_ADDRESS`.
//!
//! # Example
//!
//! ```
//! #[cfg(test)]
//! use mockito;
//!
//! #[cfg(not(test))]
//! const URL: &'static str = "https://api.twitter.com";
//!
//! #[cfg(test)]
//! const URL: &'static str = mockito::SERVER_URL;
//! ```
//!
//! Then start mocking:
//!
//! # Example
//!
//! ```
//! #[cfg(test)]
//! mod tests {
//!   use mockito::mock;
//!
//!   #[test]
//!   fn test_something() {
//!     mock("GET", "/hello")
//!       .with_status(201)
//!       .with_header("content-type", "text/plain")
//!       .with_header("x-api-key", "1234")
//!       .with_body("world")
//!       .create();
//!
//!     // Any calls to GET /hello beyond this line will respond with 201, the
//!     // `content-type: text/plain` header and the body "world".
//!   }
//! }
//! ```
//!
//! # Run your tests
//!
//! Due to the nature of this library (all your mocks are recorded on the same server running in background),
//! it is highly recommended that you **run your tests on a single thread**:
//!
//! ```sh
//! cargo test -- --test-threads=1
//!
//! # Same, but using an environment variable
//! RUST_TEST_THREADS=1 cargo test
//! ```
//!
//! In some situations, when you're *always* testing/mocking different routes and never need to reset
//! or override the existing mocks, you might get away with running your tests on multiple threads.
//!
//! # Matching by header
//!
//! Mockito currently matches by method and path, but also by headers. The header field letter case is ignored.
//!
//! # Example
//!
//! ```
//! use mockito::mock;
//!
//! mock("GET", "/hello")
//!   .match_header("content-type", "application/json")
//!   .with_body("{'hello': 'world'}")
//!   .create();
//!
//! mock("GET", "/hello")
//!   .match_header("content-type", "text/plain")
//!   .with_body("world")
//!   .create();
//!
//! // JSON requests to GET /hello will respond with JSON, while plain requests
//! // will respond with text.
//! ```
//!
//! # Cleaning up
//!
//! Even though **mocks are matched in reverse order** (most recent one wins), in some situations
//! it might be useful to clean up right after the test. There are multiple ways of doing this.
//!
//! By using a closure:
//!
//! # Example
//!
//! ```
//! use mockito::mock;
//!
//! mock("GET", "/hello")
//!   .with_body("world")
//!   .create_for(|| {
//!     // mock only valid for the lifetime of this closure
//!     // NOTE: it might still be accessible by separate threads
//!   });
//! ```
//!
//! By calling `remove()` on the mock:
//!
//! # Example
//!
//! ```
//! use mockito::mock;
//!
//! let mut mock = mock("GET", "/hello");
//! mock.with_body("world").create();
//!
//! // do your thing
//!
//! mock.remove();
//! ```
//!
//! By calling `reset()` to **remove all mocks**:
//!
//! # Example
//!
//! ```
//! use mockito::reset;
//!
//! reset();
//! ```
//!

extern crate hyper;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate rand;

mod server;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use hyper::client::Client;
use hyper::server::Request;
use hyper::header::{Headers, ContentType, Connection};
use rand::{thread_rng, Rng};

///
/// Points to the address the mock server is running at.
/// Can be used with `std::net::TcpStream`.
///
pub const SERVER_ADDRESS: &'static str = "0.0.0.0:1234";

///
/// Points to the URL the mock server is running at.
///
pub const SERVER_URL: &'static str = "http://0.0.0.0:1234";

///
/// Initializes a mock for the provided `method` and `path`.
///
/// The mock is registered to the server only after the `create()` method has been called.
///
/// # Example
///
/// ```
/// use mockito::mock;
///
/// mock("GET", "/");
/// mock("POST", "/users");
/// mock("DELETE", "/users?id=1");
/// ```
///
pub fn mock(method: &str, path: &str) -> Mock {
    Mock::new(method, path)
}

///
/// Removes all the mocks stored on the server.
///
pub fn reset() {
    server::try_start();

    Client::new()
        .delete(&[SERVER_URL, "/mocks"].join(""))
        .send()
        .unwrap();
}

///
/// Stores information about a mocked request. Should be initialized via `mockito::mock()`.
///
#[derive(PartialEq, Debug)]
pub struct Mock {
    id: String,
    method: String,
    path: String,
    headers: HashMap<String, String>,
    response: MockResponse,
}

impl Mock {
    fn new(method: &str, path: &str) -> Self {
        Mock {
            id: thread_rng().gen_ascii_chars().take(24).collect(),
            method: method.to_owned().to_uppercase(),
            path: path.to_owned(),
            headers: HashMap::new(),
            response: MockResponse::new(),
        }
    }

    ///
    /// Allows matching a particular request header when responding with a mock.
    ///
    /// When matching a request, the field letter case is ignored.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").match_header("content-type", "application/json");
    /// ```
    ///
    /// Like most other `Mock` methods, it allows chanining:
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/")
    ///   .match_header("content-type", "application/json")
    ///   .match_header("authorization", "password");
    /// ```
    ///
    pub fn match_header(&mut self, field: &str, value: &str) -> &mut Self {
        self.headers.insert(field.to_owned(), value.to_owned());

        self
    }

    ///
    /// Sets the status code of the mock response. The default status code is 200.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_status(201);
    /// ```
    ///
    pub fn with_status(&mut self, status: usize) -> &mut Self {
        self.response.status = status;

        self
    }

    ///
    /// Sets a header of the mock response.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_header("content-type", "application/json");
    /// ```
    ///
    pub fn with_header(&mut self, field: &str, value: &str) -> &mut Self {
        self.response.headers.insert(field.to_owned(), value.to_owned());

        self
    }

    ///
    /// Sets the body of the mock response. Its `Content-Length` is handled automatically.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body("hello world");
    /// ```
    ///
    pub fn with_body(&mut self, body: &str) -> &mut Self {
        self.response.body = body.to_owned();

        self
    }

    ///
    /// Sets the body of the mock response from the contents of a file stored under `path`.
    /// Its `Content-Length` is handled automatically.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body_from_file("tests/files/simple.http");
    /// ```
    ///
    pub fn with_body_from_file(&mut self, path: &str) -> &mut Self {
        let mut file = File::open(path).unwrap();
        let mut body = String::new();

        file.read_to_string(&mut body).unwrap();

        self.response.body = body;

        self
    }

    ///
    /// Registers the mock to the server - your mock will be served only after calling this method.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body("hello world").create();
    /// ```
    ///
    pub fn create(&mut self) -> &mut Self {
        server::try_start();

        let mut headers = Headers::new();
        headers.set_raw("x-mock-id", vec!(self.id.as_bytes().to_vec()));
        headers.set_raw("x-mock-method", vec!(self.method.as_bytes().to_vec()));
        headers.set_raw("x-mock-path", vec!(self.path.as_bytes().to_vec()));

        for (field, value) in &self.headers {
            headers.set_raw("x-mock-".to_string() + field, vec!(value.as_bytes().to_vec()));
        }

        let body = serde_json::to_string(&self.response).unwrap();
        Client::new()
            .post(&[SERVER_URL, "/mocks"].join(""))
            .headers(headers)
            .header(ContentType::json())
            .header(Connection::close())
            .body(&body)
            .send()
            .unwrap();

        self
    }

    ///
    /// Registers the mock to the server, executes the passed closure and removes the mock afterwards.
    ///
    /// **NOTE:** During the closure lifetime, the mock might still be available to seperate threads.
    ///
    /// # Example
    ///
    /// ```
    /// use std::thread::{sleep};
    /// use std::time::Duration;
    /// use mockito::mock;
    ///
    /// mock("GET", "/").with_body("hello world").create_for(|| {
    ///   // This mock will only be available for the next 1 second
    ///   sleep(Duration::new(1, 0));
    /// });
    /// ```
    ///
    pub fn create_for<F: Fn() -> ()>(&mut self, environment: F) -> &mut Self {
        self.create();
        environment();
        self.remove();

        self
    }

    ///
    /// Removes the current mock from the server.
    ///
    /// # Example
    ///
    /// ```
    /// use mockito::mock;
    ///
    /// let mut mock = mock("GET", "/");
    /// mock.with_body("hello world").create();
    ///
    /// // stuff
    ///
    /// mock.remove();
    /// ```
    ///
    pub fn remove(&self) {
        server::try_start();

        let mut headers = Headers::new();
        headers.set_raw("x-mock-id", vec!(self.id.as_bytes().to_vec()));

        Client::new()
            .delete(&[SERVER_URL, "/mocks"].join(""))
            .headers(headers)
            .header(Connection::close())
            .send()
            .unwrap();
    }

    #[allow(missing_docs)]
    pub fn matches(&self, request: &Request) -> bool {
        self.method_matches(request)
            && self.path_matches(request)
            && self.headers_match(request)
    }

    fn method_matches(&self, request: &Request) -> bool {
        self.method == request.method.to_string().to_uppercase()
    }

    fn path_matches(&self, request: &Request) -> bool {
        self.path == request.uri.to_string()
    }

    fn headers_match(&self, request: &Request) -> bool {
        for (field, value) in self.headers.iter() {
            match request.headers.get_raw(&field) {
                Some(request_header_value) => {
                    let bytes: Vec<u8> = request_header_value.iter().flat_map(|el| el.iter().cloned()).collect();

                    if value == &String::from_utf8(bytes).unwrap() { continue }

                    return false
                },
                _ => return false
            }
        }

        true
    }
}

const DEFAULT_RESPONSE_STATUS: usize = 200;

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct MockResponse {
    status: usize,
    headers: HashMap<String, String>,
    body: String,
}

impl MockResponse {
    pub fn new() -> Self {
        MockResponse {
            status: DEFAULT_RESPONSE_STATUS,
            headers: HashMap::new(),
            body: String::new(),
        }
    }
}
<|endoftext|>


<commit_before>//! Enigo lets you simulate mouse and keyboard input-events as if they were
//! made by the actual hardware. The goal is to make it available on different
//! operating systems like Linux, macOS and Windows – possibly many more but
//! [Redox](https://redox-os.org/) and *BSD are planned. Please see the
//! [Repo](https://github.com/enigo-rs/enigo) for the current status.
//!
//! I consider this library in an early alpha status, the API will change in
//! in the future. The keyboard handling is far from being very usable. I plan
//! to build a simple
//! [DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
//! that will resemble something like:
//!
//! `"hello {+SHIFT}world{-SHIFT} and break line{ENTER}"`
//!
//! The current status is that you can just print
//! [unicode](http://unicode.org/)
//! characters like [emoji](http://getemoji.com/) without the `{+SHIFT}`
//! [DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
//! or any other "special" key on the Linux, macOS and Windows operating system.
//!
//! Possible use cases could be for testing user interfaces on different
//! plattforms,
//! building remote control applications or just automating tasks for user
//! interfaces unaccessible by a public API or scripting laguage.
//!
//! For the keyboard there are currently two modes you can use. The first mode
//! is represented by the [key_sequence]() function
//! its purpose is to simply write unicode characters. This is independent of
//! the keyboardlayout. Please note that
//! you're not be able to use modifier keys like Control
//! to influence the outcome. If you want to use modifier keys to e.g.
//! copy/paste
//! use the Layout variant. Please note that this is indeed layout dependent.

//! # Examples
//! ```no_run
//! use enigo::*;
//! let mut enigo = Enigo::new();
//! //paste
//! enigo.key_down(Key::Control);
//! enigo.key_click(Key::Layout('v'));
//! enigo.key_up(Key::Control);
//! ```
//!
//! ```no_run
//! use enigo::*;
//! let mut enigo = Enigo::new();
//! enigo.mouse_move_to(500, 200);
//! enigo.mouse_down(MouseButton::Left);
//! enigo.mouse_move_relative(100, 100);
//! enigo.mouse_up(MouseButton::Left);
//! enigo.key_sequence("hello world");
//! ```
#![deny(missing_docs)]

#[cfg(target_os = "macos")]
#[macro_use]
extern crate objc;

// TODO(dustin) use interior mutability not &mut self

#[cfg(target_os = "windows")]
mod win;
#[cfg(target_os = "windows")]
pub use win::Enigo;

#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
pub use macos::Enigo;

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
pub use crate::linux::Enigo;

/// DSL parser module
pub mod dsl;

#[cfg(feature = "with_serde")]
#[macro_use]
extern crate serde_derive;

#[cfg(feature = "with_serde")]
extern crate serde;

#[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
/// MouseButton represents a mouse button,
/// and is used in for example
/// [mouse_click](trait.MouseControllable.html#tymethod.mouse_click).
/// WARNING: Types with the prefix Scroll
/// IS NOT intended to be used, and may not work on
/// all operating systems.
pub enum MouseButton {
    /// Left mouse button
    Left,
    /// Middle mouse button
    Middle,
    /// Right mouse button
    Right,

    /// Scroll up button
    ScrollUp,
    /// Left right button
    ScrollDown,
    /// Left right button
    ScrollLeft,
    /// Left right button
    ScrollRight,
}

/// Representing an interface and a set of mouse functions every
/// operating system implementation _should_ implement.
pub trait MouseControllable {
    /// Lets the mouse cursor move to the specified x and y coordinates.
    ///
    /// The topleft corner of your monitor screen is x=0 y=0. Move
    /// the cursor down the screen by increasing the y and to the right
    /// by increasing x coordinate.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_move_to(500, 200);
    /// ```
    fn mouse_move_to(&mut self, x: i32, y: i32);

    /// Lets the mouse cursor move the specified amount in the x and y
    /// direction.
    ///
    /// The amount specified in the x and y parameters are added to the
    /// current location of the mouse cursor. A positive x values lets
    /// the mouse cursor move an amount of `x` pixels to the right. A negative
    /// value for `x` lets the mouse cursor go to the left. A positive value
    /// of y
    /// lets the mouse cursor go down, a negative one lets the mouse cursor go
    /// up.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_move_relative(100, 100);
    /// ```
    fn mouse_move_relative(&mut self, x: i32, y: i32);

    /// Push down one of the mouse buttons
    ///
    /// Push down the mouse button specified by the parameter `button` of
    /// type [MouseButton](enum.MouseButton.html)
    /// and holds it until it is released by
    /// [mouse_up](trait.MouseControllable.html#tymethod.mouse_up).
    /// Calls to [mouse_move_to](trait.MouseControllable.html#tymethod.
    /// mouse_move_to) or
    /// [mouse_move_relative](trait.MouseControllable.html#tymethod.
    /// mouse_move_relative)
    /// will work like expected and will e.g. drag widgets or highlight text.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_down(MouseButton::Left);
    /// ```
    fn mouse_down(&mut self, button: MouseButton);

    /// Lift up a pushed down mouse button
    ///
    /// Lift up a previously pushed down button (by invoking
    /// [mouse_down](trait.MouseControllable.html#tymethod.mouse_down)).
    /// If the button was not pushed down or consecutive calls without
    /// invoking [mouse_down](trait.MouseControllable.html#tymethod.mouse_down)
    /// will emit lift up events. It depends on the
    /// operating system whats actually happening – my guess is it will just
    /// get ignored.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_up(MouseButton::Right);
    /// ```
    fn mouse_up(&mut self, button: MouseButton);

    /// Click a mouse button
    ///
    /// it's esentially just a consecutive invokation of
    /// [mouse_down](trait.MouseControllable.html#tymethod.mouse_down) followed
    /// by a [mouse_up](trait.MouseControllable.html#tymethod.mouse_up). Just
    /// for
    /// convenience.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_click(MouseButton::Right);
    /// ```
    fn mouse_click(&mut self, button: MouseButton);

    /// Scroll the mouse (wheel) left or right
    ///
    /// Positive numbers for length lets the mouse wheel scroll to the right
    /// and negative ones to the left. The value that is specified translates
    /// to `lines` defined by the operating system and is essentially one 15°
    /// (click)rotation on the mouse wheel. How many lines it moves depends
    /// on the current setting in the operating system.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_scroll_x(2);
    /// ```
    fn mouse_scroll_x(&mut self, length: i32);

    /// Scroll the mouse (wheel) up or down
    ///
    /// Positive numbers for length lets the mouse wheel scroll down
    /// and negative ones up. The value that is specified translates
    /// to `lines` defined by the operating system and is essentially one 15°
    /// (click)rotation on the mouse wheel. How many lines it moves depends
    /// on the current setting in the operating system.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_scroll_y(2);
    /// ```
    fn mouse_scroll_y(&mut self, length: i32);
}

/// A key on the keyboard.
/// For alphabetical keys, use Key::Layout for a system independent key.
/// If a key is missing, you can use the raw keycode with Key::Raw.
#[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Key {
    /// alt key on Linux and Windows (option key on macOS)
    Alt,
    /// backspace key
    Backspace,
    /// caps lock key
    CapsLock,
    #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
    /// command key on macOS (super key on Linux, windows key on Windows)
    Command,
    /// control key
    Control,
    /// delete key
    Delete,
    /// down arrow key
    DownArrow,
    /// end key
    End,
    /// escape key (esc)
    Escape,
    /// F1 key
    F1,
    /// F10 key
    F10,
    /// F11 key
    F11,
    /// F12 key
    F12,
    /// F2 key
    F2,
    /// F3 key
    F3,
    /// F4 key
    F4,
    /// F5 key
    F5,
    /// F6 key
    F6,
    /// F7 key
    F7,
    /// F8 key
    F8,
    /// F9 key
    F9,
    /// home key
    Home,
    /// left arrow key
    LeftArrow,
    /// meta key (also known as "windows", "super", and "command")
    Meta,
    /// option key on macOS (alt key on Linux and Windows)
    Option,
    /// page down key
    PageDown,
    /// page up key
    PageUp,
    /// return key
    Return,
    /// right arrow key
    RightArrow,
    /// shift key
    Shift,
    /// space key
    Space,
    #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
    /// super key on linux (command key on macOS, windows key on Windows)
    Super,
    /// tab key (tabulator)
    Tab,
    /// up arrow key
    UpArrow,
    #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
    /// windows key on Windows (super key on Linux, command key on macOS)
    Windows,
    /// keyboard layout dependent key
    Layout(char),
    /// raw keycode eg 0x38
    Raw(u16),
}

/// Representing an interface and a set of keyboard functions every
/// operating system implementation _should_ implement.
pub trait KeyboardControllable {
    /// Types the string parsed with DSL.
    ///
    /// Typing {+SHIFT}hello{-SHIFT} becomes HELLO.
    /// TODO: Full documentation
    fn key_sequence_parse(&mut self, sequence: &str)
    where
        Self: Sized,
    {
        self.key_sequence_parse_try(sequence)
            .expect("Could not parse sequence");
    }
    /// Same as key_sequence_parse except returns any errors
    fn key_sequence_parse_try(&mut self, sequence: &str) -> Result<(), dsl::ParseError>
    where
        Self: Sized,
    {
        dsl::eval(self, sequence)
    }

    /// Types the string
    ///
    /// Emits keystrokes such that the given string is inputted.
    ///
    /// You can use many unicode here like: ❤. This works
    /// regadless of the current keyboardlayout.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.key_sequence("hello world ❤");
    /// ```
    fn key_sequence(&mut self, sequence: &str);

    /// presses a given key down
    fn key_down(&mut self, key: Key);

    /// release a given key formally pressed down by
    /// [key_down](trait.KeyboardControllable.html#tymethod.key_down)
    fn key_up(&mut self, key: Key);

    /// Much like the
    /// [key_down](trait.KeyboardControllable.html#tymethod.key_down) and
    /// [key_up](trait.KeyboardControllable.html#tymethod.key_up)
    /// function they're just invoked consecutively
    fn key_click(&mut self, key: Key);
}

impl Enigo {
    /// Constructs a new `Enigo` instance.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// ```
    pub fn new() -> Self {
        Self::default()
    }
}

use std::fmt;

impl fmt::Debug for Enigo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Enigo")
    }
}
<commit_msg>Add Hash derive<commit_after>//! Enigo lets you simulate mouse and keyboard input-events as if they were
//! made by the actual hardware. The goal is to make it available on different
//! operating systems like Linux, macOS and Windows – possibly many more but
//! [Redox](https://redox-os.org/) and *BSD are planned. Please see the
//! [Repo](https://github.com/enigo-rs/enigo) for the current status.
//!
//! I consider this library in an early alpha status, the API will change in
//! in the future. The keyboard handling is far from being very usable. I plan
//! to build a simple
//! [DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
//! that will resemble something like:
//!
//! `"hello {+SHIFT}world{-SHIFT} and break line{ENTER}"`
//!
//! The current status is that you can just print
//! [unicode](http://unicode.org/)
//! characters like [emoji](http://getemoji.com/) without the `{+SHIFT}`
//! [DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
//! or any other "special" key on the Linux, macOS and Windows operating system.
//!
//! Possible use cases could be for testing user interfaces on different
//! plattforms,
//! building remote control applications or just automating tasks for user
//! interfaces unaccessible by a public API or scripting laguage.
//!
//! For the keyboard there are currently two modes you can use. The first mode
//! is represented by the [key_sequence]() function
//! its purpose is to simply write unicode characters. This is independent of
//! the keyboardlayout. Please note that
//! you're not be able to use modifier keys like Control
//! to influence the outcome. If you want to use modifier keys to e.g.
//! copy/paste
//! use the Layout variant. Please note that this is indeed layout dependent.

//! # Examples
//! ```no_run
//! use enigo::*;
//! let mut enigo = Enigo::new();
//! //paste
//! enigo.key_down(Key::Control);
//! enigo.key_click(Key::Layout('v'));
//! enigo.key_up(Key::Control);
//! ```
//!
//! ```no_run
//! use enigo::*;
//! let mut enigo = Enigo::new();
//! enigo.mouse_move_to(500, 200);
//! enigo.mouse_down(MouseButton::Left);
//! enigo.mouse_move_relative(100, 100);
//! enigo.mouse_up(MouseButton::Left);
//! enigo.key_sequence("hello world");
//! ```
#![deny(missing_docs)]

#[cfg(target_os = "macos")]
#[macro_use]
extern crate objc;

// TODO(dustin) use interior mutability not &mut self

#[cfg(target_os = "windows")]
mod win;
#[cfg(target_os = "windows")]
pub use win::Enigo;

#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
pub use macos::Enigo;

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
pub use crate::linux::Enigo;

/// DSL parser module
pub mod dsl;

#[cfg(feature = "with_serde")]
#[macro_use]
extern crate serde_derive;

#[cfg(feature = "with_serde")]
extern crate serde;

#[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
/// MouseButton represents a mouse button,
/// and is used in for example
/// [mouse_click](trait.MouseControllable.html#tymethod.mouse_click).
/// WARNING: Types with the prefix Scroll
/// IS NOT intended to be used, and may not work on
/// all operating systems.
pub enum MouseButton {
    /// Left mouse button
    Left,
    /// Middle mouse button
    Middle,
    /// Right mouse button
    Right,

    /// Scroll up button
    ScrollUp,
    /// Left right button
    ScrollDown,
    /// Left right button
    ScrollLeft,
    /// Left right button
    ScrollRight,
}

/// Representing an interface and a set of mouse functions every
/// operating system implementation _should_ implement.
pub trait MouseControllable {
    /// Lets the mouse cursor move to the specified x and y coordinates.
    ///
    /// The topleft corner of your monitor screen is x=0 y=0. Move
    /// the cursor down the screen by increasing the y and to the right
    /// by increasing x coordinate.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_move_to(500, 200);
    /// ```
    fn mouse_move_to(&mut self, x: i32, y: i32);

    /// Lets the mouse cursor move the specified amount in the x and y
    /// direction.
    ///
    /// The amount specified in the x and y parameters are added to the
    /// current location of the mouse cursor. A positive x values lets
    /// the mouse cursor move an amount of `x` pixels to the right. A negative
    /// value for `x` lets the mouse cursor go to the left. A positive value
    /// of y
    /// lets the mouse cursor go down, a negative one lets the mouse cursor go
    /// up.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_move_relative(100, 100);
    /// ```
    fn mouse_move_relative(&mut self, x: i32, y: i32);

    /// Push down one of the mouse buttons
    ///
    /// Push down the mouse button specified by the parameter `button` of
    /// type [MouseButton](enum.MouseButton.html)
    /// and holds it until it is released by
    /// [mouse_up](trait.MouseControllable.html#tymethod.mouse_up).
    /// Calls to [mouse_move_to](trait.MouseControllable.html#tymethod.
    /// mouse_move_to) or
    /// [mouse_move_relative](trait.MouseControllable.html#tymethod.
    /// mouse_move_relative)
    /// will work like expected and will e.g. drag widgets or highlight text.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_down(MouseButton::Left);
    /// ```
    fn mouse_down(&mut self, button: MouseButton);

    /// Lift up a pushed down mouse button
    ///
    /// Lift up a previously pushed down button (by invoking
    /// [mouse_down](trait.MouseControllable.html#tymethod.mouse_down)).
    /// If the button was not pushed down or consecutive calls without
    /// invoking [mouse_down](trait.MouseControllable.html#tymethod.mouse_down)
    /// will emit lift up events. It depends on the
    /// operating system whats actually happening – my guess is it will just
    /// get ignored.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_up(MouseButton::Right);
    /// ```
    fn mouse_up(&mut self, button: MouseButton);

    /// Click a mouse button
    ///
    /// it's esentially just a consecutive invokation of
    /// [mouse_down](trait.MouseControllable.html#tymethod.mouse_down) followed
    /// by a [mouse_up](trait.MouseControllable.html#tymethod.mouse_up). Just
    /// for
    /// convenience.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_click(MouseButton::Right);
    /// ```
    fn mouse_click(&mut self, button: MouseButton);

    /// Scroll the mouse (wheel) left or right
    ///
    /// Positive numbers for length lets the mouse wheel scroll to the right
    /// and negative ones to the left. The value that is specified translates
    /// to `lines` defined by the operating system and is essentially one 15°
    /// (click)rotation on the mouse wheel. How many lines it moves depends
    /// on the current setting in the operating system.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_scroll_x(2);
    /// ```
    fn mouse_scroll_x(&mut self, length: i32);

    /// Scroll the mouse (wheel) up or down
    ///
    /// Positive numbers for length lets the mouse wheel scroll down
    /// and negative ones up. The value that is specified translates
    /// to `lines` defined by the operating system and is essentially one 15°
    /// (click)rotation on the mouse wheel. How many lines it moves depends
    /// on the current setting in the operating system.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.mouse_scroll_y(2);
    /// ```
    fn mouse_scroll_y(&mut self, length: i32);
}

/// A key on the keyboard.
/// For alphabetical keys, use Key::Layout for a system independent key.
/// If a key is missing, you can use the raw keycode with Key::Raw.
#[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// alt key on Linux and Windows (option key on macOS)
    Alt,
    /// backspace key
    Backspace,
    /// caps lock key
    CapsLock,
    #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
    /// command key on macOS (super key on Linux, windows key on Windows)
    Command,
    /// control key
    Control,
    /// delete key
    Delete,
    /// down arrow key
    DownArrow,
    /// end key
    End,
    /// escape key (esc)
    Escape,
    /// F1 key
    F1,
    /// F10 key
    F10,
    /// F11 key
    F11,
    /// F12 key
    F12,
    /// F2 key
    F2,
    /// F3 key
    F3,
    /// F4 key
    F4,
    /// F5 key
    F5,
    /// F6 key
    F6,
    /// F7 key
    F7,
    /// F8 key
    F8,
    /// F9 key
    F9,
    /// home key
    Home,
    /// left arrow key
    LeftArrow,
    /// meta key (also known as "windows", "super", and "command")
    Meta,
    /// option key on macOS (alt key on Linux and Windows)
    Option,
    /// page down key
    PageDown,
    /// page up key
    PageUp,
    /// return key
    Return,
    /// right arrow key
    RightArrow,
    /// shift key
    Shift,
    /// space key
    Space,
    #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
    /// super key on linux (command key on macOS, windows key on Windows)
    Super,
    /// tab key (tabulator)
    Tab,
    /// up arrow key
    UpArrow,
    #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
    /// windows key on Windows (super key on Linux, command key on macOS)
    Windows,
    /// keyboard layout dependent key
    Layout(char),
    /// raw keycode eg 0x38
    Raw(u16),
}

/// Representing an interface and a set of keyboard functions every
/// operating system implementation _should_ implement.
pub trait KeyboardControllable {
    /// Types the string parsed with DSL.
    ///
    /// Typing {+SHIFT}hello{-SHIFT} becomes HELLO.
    /// TODO: Full documentation
    fn key_sequence_parse(&mut self, sequence: &str)
    where
        Self: Sized,
    {
        self.key_sequence_parse_try(sequence)
            .expect("Could not parse sequence");
    }
    /// Same as key_sequence_parse except returns any errors
    fn key_sequence_parse_try(&mut self, sequence: &str) -> Result<(), dsl::ParseError>
    where
        Self: Sized,
    {
        dsl::eval(self, sequence)
    }

    /// Types the string
    ///
    /// Emits keystrokes such that the given string is inputted.
    ///
    /// You can use many unicode here like: ❤. This works
    /// regadless of the current keyboardlayout.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// enigo.key_sequence("hello world ❤");
    /// ```
    fn key_sequence(&mut self, sequence: &str);

    /// presses a given key down
    fn key_down(&mut self, key: Key);

    /// release a given key formally pressed down by
    /// [key_down](trait.KeyboardControllable.html#tymethod.key_down)
    fn key_up(&mut self, key: Key);

    /// Much like the
    /// [key_down](trait.KeyboardControllable.html#tymethod.key_down) and
    /// [key_up](trait.KeyboardControllable.html#tymethod.key_up)
    /// function they're just invoked consecutively
    fn key_click(&mut self, key: Key);
}

impl Enigo {
    /// Constructs a new `Enigo` instance.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// ```
    pub fn new() -> Self {
        Self::default()
    }
}

use std::fmt;

impl fmt::Debug for Enigo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Enigo")
    }
}
<|endoftext|>


<commit_before>#[link(name="index")];
#[pkgid = "index#0.1"];
#[crate_type="rlib"];

#[deny(non_camel_case_types)];
#[deny(missing_doc)];

//! Boolean algebra library for indexing.

/// Is returned by 'index_of'.
#[deriving(Eq)]
pub enum IndexMatch {
	/// Item found at index.
	Found(uint),
	/// Item not found, but can be inserted at index.
	FoundLarger(uint)
}

/// Index is a struct used for doing algebraic set operations.
/// It contains a hidden vector of the type 'T'.
/// The items are sorted in ascending order.
pub struct Index<T> {
	priv ids: ~[T],
}

impl<T: Clone + Ord + Eq> Index<T> {

	/// Constructs a new Index without checking the order.
	/// This method takes ownership of the vector.
	pub fn new(data: ~[T]) -> Index<T> { Index { ids: data } }

	/// Checks that each item in vector is larger than previous one.
	pub fn check_order(data: &~[T]) -> bool {
		!data.windows(2).any(|w| w[0] >= w[1])
	}

	/// Clones the vector.
	pub fn to_vec(&self) -> ~[T] { self.ids.clone() }

	/// Returns Found(i) if the item was found in the Index.
	/// Returns FoundNext(i), the index to insert, if the item was not found.
	/// Worst case performance: O(N).
	pub fn index_of(&self, item: &T) -> IndexMatch {
		let list = &self.ids;
		let n = list.len() as int;
		if n == 0 { return FoundLarger(0u); }
		let mut low: int = 0;
		let mut high: int = n - 1;
		while low <= high {
			let i: int = (low + high) / 2;
			if list[i] < *item {
				low = i + 1;
				continue;
			}
			if list[i] > *item {
				high = i - 1;
				continue;
			}

			return Found(i as uint);
		}

		FoundLarger(low as uint)
	}

	/// Inserts a new item.
	pub fn insert(&mut self, item: T) -> bool {
		match self.index_of(&item) {
			Found(_) => false,
			FoundLarger(i) => {
				self.ids.insert(i, item);
				true
			},
		}
	}
}

/// Creates a new Index containing all items from both arguments.
impl<T: Ord + Eq + Clone> Add<Index<T>, Index<T>> for Index<T> {
	fn add(&self, rhs: &Index<T>) -> Index<T> {
		Index { ids: or(self.ids, rhs.ids) }
	}
}

/// Creates a new Index containing items from both arguments.
impl<T: Ord + Eq + Clone> Mul<Index<T>, Index<T>> for Index<T> {
	fn mul(&self, rhs: &Index<T>) -> Index<T> {
		Index { ids: and(self.ids, rhs.ids) }
	}
}

/// Creates a new Index containing items from the left argument but not the second.
impl<T: Ord + Eq + Clone> Sub<Index<T>, Index<T>> for Index<T> {
	fn sub(&self, rhs: &Index<T>) -> Index<T> {
		Index { ids: except(self.ids, rhs.ids) }
	}
}

fn or<T: Ord + Eq + Clone>(a: &[T], b: &[T]) -> ~[T] {
	let mut i = 0;
	let mut j = 1;
	let an = a.len();
	let bn = b.len();
	let mut result: ~[T] = ~[];
	while i < an || j < an {
		let av =
			if i < an {
				&a[i]
			} else {
				&a[an - 1]
			};
		let bv =
			if j < bn {
				&b[j]
			} else {
				&b[bn - 1]
			};
		let min =
			if i >= an {
				bv
			} else if j >= bn {
				av
			} else {
				if av < bv {
					av
				} else {
					bv
				}
			};
		if i < an && min == av {
			i += 1;
		}
		if j < bn && min == bv {
			j += 1;
		}

		result.push(min.clone());
	}

	result
}

fn and<T:Ord+Eq+Clone>(a: &[T], b: &[T]) -> ~[T] {
	let mut i = 0;
	let mut j = 0;
	let an = a.len();
	let bn = b.len();
	let mut result: ~[T] = ~[];
	while i < an && j < bn {
		let av = &a[i];
		let bv = &b[j];
		let min =
			if av < bv {
				av
			} else {
				bv
			};
		let isAv = min == av;
		let isBv = min == bv;
		if isAv {
			i += 1;
		}
		if isBv {
			j += 1;
		}

		if isAv && isBv {
			result.push(min.clone());
		}
	}

	result
}

fn except<T:Ord+Eq+Clone>(a: &[T], b: &[T]) -> ~[T] {
	let mut i = 0;
	let mut j = 0;
	let an = a.len();
	let bn = b.len();
	let mut result: ~[T] = ~[];
	while i < an {
		let av = &a[i];
		let bv =
			if j < bn {
				&b[j]
			} else {
				&b[bn - 1]
			};
		let min =
			if j >= bn {
				av
			} else {
				if av < bv {
					av
				} else {
					bv
				}
			};
		let isAv = min == av;
		let isBv = min == bv;
		if isAv {
			i += 1;
		}
		if j < bn && isBv {
			j += 1;
		}
		if isAv && !isBv {
			result.push(min.clone());
		}
	}

	result
}

<commit_msg>Changed comment.<commit_after>#[link(name="index")];
#[pkgid = "index#0.1"];
#[crate_type="rlib"];

#[deny(non_camel_case_types)];
#[deny(missing_doc)];

//! Boolean algebra library for indexing.

/// Is returned by 'index_of'.
#[deriving(Eq)]
pub enum IndexMatch {
	/// Item found at index.
	Found(uint),
	/// Item not found, but can be inserted at index.
	FoundLarger(uint)
}

/// Index is a struct used for doing algebraic set operations.
/// It contains a hidden vector of the type 'T'.
/// The items are sorted in ascending order.
pub struct Index<T> {
	priv ids: ~[T],
}

impl<T: Clone + Ord + Eq> Index<T> {

	/// Constructs a new Index without checking the order.
	/// This method takes ownership of the vector.
	pub fn new(data: ~[T]) -> Index<T> { Index { ids: data } }

	/// Checks that each item in vector is larger than previous one.
	pub fn check_order(data: &~[T]) -> bool {
		!data.windows(2).any(|w| w[0] >= w[1])
	}

	/// Clones the vector.
	pub fn to_vec(&self) -> ~[T] { self.ids.clone() }

	/// Returns Found(i) if the item was found in the Index.
	/// Returns FoundNext(i), the index to insert, if the item was not found.
	/// Worst case performance: O(log(N)).
	pub fn index_of(&self, item: &T) -> IndexMatch {
		let list = &self.ids;
		let n = list.len() as int;
		if n == 0 { return FoundLarger(0u); }
		let mut low: int = 0;
		let mut high: int = n - 1;
		while low <= high {
			let i: int = (low + high) / 2;
			if list[i] < *item {
				low = i + 1;
				continue;
			}
			if list[i] > *item {
				high = i - 1;
				continue;
			}

			return Found(i as uint);
		}

		FoundLarger(low as uint)
	}

	/// Inserts a new item.
	pub fn insert(&mut self, item: T) -> bool {
		match self.index_of(&item) {
			Found(_) => false,
			FoundLarger(i) => {
				self.ids.insert(i, item);
				true
			},
		}
	}
}

/// Creates a new Index containing all items from both arguments.
impl<T: Ord + Eq + Clone> Add<Index<T>, Index<T>> for Index<T> {
	fn add(&self, rhs: &Index<T>) -> Index<T> {
		Index { ids: or(self.ids, rhs.ids) }
	}
}

/// Creates a new Index containing items from both arguments.
impl<T: Ord + Eq + Clone> Mul<Index<T>, Index<T>> for Index<T> {
	fn mul(&self, rhs: &Index<T>) -> Index<T> {
		Index { ids: and(self.ids, rhs.ids) }
	}
}

/// Creates a new Index containing items from the left argument but not the second.
impl<T: Ord + Eq + Clone> Sub<Index<T>, Index<T>> for Index<T> {
	fn sub(&self, rhs: &Index<T>) -> Index<T> {
		Index { ids: except(self.ids, rhs.ids) }
	}
}

fn or<T: Ord + Eq + Clone>(a: &[T], b: &[T]) -> ~[T] {
	let mut i = 0;
	let mut j = 1;
	let an = a.len();
	let bn = b.len();
	let mut result: ~[T] = ~[];
	while i < an || j < an {
		let av =
			if i < an {
				&a[i]
			} else {
				&a[an - 1]
			};
		let bv =
			if j < bn {
				&b[j]
			} else {
				&b[bn - 1]
			};
		let min =
			if i >= an {
				bv
			} else if j >= bn {
				av
			} else {
				if av < bv {
					av
				} else {
					bv
				}
			};
		if i < an && min == av {
			i += 1;
		}
		if j < bn && min == bv {
			j += 1;
		}

		result.push(min.clone());
	}

	result
}

fn and<T:Ord+Eq+Clone>(a: &[T], b: &[T]) -> ~[T] {
	let mut i = 0;
	let mut j = 0;
	let an = a.len();
	let bn = b.len();
	let mut result: ~[T] = ~[];
	while i < an && j < bn {
		let av = &a[i];
		let bv = &b[j];
		let min =
			if av < bv {
				av
			} else {
				bv
			};
		let isAv = min == av;
		let isBv = min == bv;
		if isAv {
			i += 1;
		}
		if isBv {
			j += 1;
		}

		if isAv && isBv {
			result.push(min.clone());
		}
	}

	result
}

fn except<T:Ord+Eq+Clone>(a: &[T], b: &[T]) -> ~[T] {
	let mut i = 0;
	let mut j = 0;
	let an = a.len();
	let bn = b.len();
	let mut result: ~[T] = ~[];
	while i < an {
		let av = &a[i];
		let bv =
			if j < bn {
				&b[j]
			} else {
				&b[bn - 1]
			};
		let min =
			if j >= bn {
				av
			} else {
				if av < bv {
					av
				} else {
					bv
				}
			};
		let isAv = min == av;
		let isBv = min == bv;
		if isAv {
			i += 1;
		}
		if j < bn && isBv {
			j += 1;
		}
		if isAv && !isBv {
			result.push(min.clone());
		}
	}

	result
}

<|endoftext|>


<commit_before>extern crate rand;

pub mod mep;
pub use mep::*;

///SISO is an algorithm that takes a static amount of inputs and produces a static number of outputs.
pub trait SISO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that must be the correct number of inputs and produces an
    ///iterator that provides the static number of outputs.
    fn compute(&'a self, inputs: &'a [In]) -> Self::Iter;
}

///SIVO is an algorithm that takes a static amount of inputs and produces a variable number of outputs.
pub trait SIVO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that must be the correct number of inputs along with the number of outputs.
    ///It returns an iterator that provides the required number of outputs.
    fn compute(&'a self, inputs: &'a [In], n_outputs: usize) -> Self::Iter;
}

///VISO is an algorithm that takes a variable amount of inputs and produces a static number of outputs.
pub trait VISO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that can be any number of inputs and produces an
    ///iterator that provides the static number of outputs.
    fn compute(&'a self, inputs: &'a [In]) -> Self::Iter;
}

///VIVO is an algorithm that takes a variable amount of inputs and produces a variable number of outputs.
pub trait VIVO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that can be any number of inputs along with the number of outputs.
    ///It returns an iterator that provides the required number of outputs.
    fn compute(&'a self, inputs: &'a [In], n_outputs: usize) -> Self::Iter;
}

///A learning algorithm is one that can be trained and performs computations.
pub trait Learning<R, In, Out>
    where R: rand::Rng
{
    ///Train requires inputs and outputs required by the system and an Rng to introduce randomness.
    ///Level should scale linearly with the amount of time spent training and level 1 should represent the smallest
    ///amount of training possible.
    fn train(&mut self, level: u32, inputs: &[In], outputs: &[Out], rng: &mut R);
}

///Genetic is a trait that allows genetic manipulation. Genetic algorithms require duplication, which is why
///there is a requirement for Clone. It is parameterized with an Rng (R) type so that the algorithms can extract random
///data when mating so that mating can happen randomly. In and Out are parameters specifying the inputs and outputs of
///the learning algorithm component of the genetic algorithm.
///
///Note: This API is highly likely to change before version 1.0.
pub trait Genetic<R, In, Out> : Clone
    where R: rand::Rng
{
    ///The mate function takes a tuple of two parent references and an Rng, then returns a new child.
    fn mate(parents: (&Self, &Self), rng: &mut R) -> Self;
    ///The mutate function performs a unit mutation. A single, several, or no actual mutations may occour.
    fn mutate(&mut self, rng: &mut R);
}
<commit_msg>fixed trait parameters for Genetic<commit_after>extern crate rand;

pub mod mep;
pub use mep::*;

///SISO is an algorithm that takes a static amount of inputs and produces a static number of outputs.
pub trait SISO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that must be the correct number of inputs and produces an
    ///iterator that provides the static number of outputs.
    fn compute(&'a self, inputs: &'a [In]) -> Self::Iter;
}

///SIVO is an algorithm that takes a static amount of inputs and produces a variable number of outputs.
pub trait SIVO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that must be the correct number of inputs along with the number of outputs.
    ///It returns an iterator that provides the required number of outputs.
    fn compute(&'a self, inputs: &'a [In], n_outputs: usize) -> Self::Iter;
}

///VISO is an algorithm that takes a variable amount of inputs and produces a static number of outputs.
pub trait VISO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that can be any number of inputs and produces an
    ///iterator that provides the static number of outputs.
    fn compute(&'a self, inputs: &'a [In]) -> Self::Iter;
}

///VIVO is an algorithm that takes a variable amount of inputs and produces a variable number of outputs.
pub trait VIVO<'a, In, Out> {
    ///The iterator type returned from compute. Its lifetime is tied to self.
    type Iter: Iterator<Item=Out> + 'a;
    ///Compute is provided an input slice that can be any number of inputs along with the number of outputs.
    ///It returns an iterator that provides the required number of outputs.
    fn compute(&'a self, inputs: &'a [In], n_outputs: usize) -> Self::Iter;
}

///A learning algorithm is one that can be trained and performs computations.
pub trait Learning<R, In, Out>
    where R: rand::Rng
{
    ///Train requires inputs and outputs required by the system and an Rng to introduce randomness.
    ///Level should scale linearly with the amount of time spent training and level 1 should represent the smallest
    ///amount of training possible.
    fn train(&mut self, level: u32, inputs: &[In], outputs: &[Out], rng: &mut R);
}

///Genetic is a trait that allows genetic manipulation. Genetic algorithms require duplication, which is why
///there is a requirement for Clone. It is parameterized with an Rng (R) type so that the algorithms can extract random
///data when mating so that mating can happen randomly. In and Out are parameters specifying the inputs and outputs of
///the learning algorithm component of the genetic algorithm.
///
///Note: This API is highly likely to change before version 1.0.
pub trait Genetic<R> : Clone
    where R: rand::Rng
{
    ///The mate function takes a tuple of two parent references and an Rng, then returns a new child.
    fn mate(parents: (&Self, &Self), rng: &mut R) -> Self;
    ///The mutate function performs a unit mutation. A single, several, or no actual mutations may occour.
    fn mutate(&mut self, rng: &mut R);
}
<|endoftext|>


<commit_before>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate serialize;

use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream};
use std::vec::Vec;
use conn::{Conn, Connection};
use data::{Config, IrcReader, IrcWriter, Message};

pub mod conn;
pub mod data;

pub trait Bot<'a> {
    fn send_nick(&self, nick: &str) -> IoResult<()>;
    fn send_user(&self, username: &str, real_name: &str) -> IoResult<()>;
    fn send_join(&self, chan: &str) -> IoResult<()>;
    fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()>;
    fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()>;
    fn send_invite(&self, person: &str, chan: &str) -> IoResult<()>;
    fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()>;
    fn identify(&self) -> IoResult<()>;
    fn output(&mut self) -> IoResult<()>;
    fn config(&self) -> &Config;
}

pub struct IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub conn: RefCell<Connection<T, U>>,
    pub config: Config,
    process: RefCell<|&IrcBot<T, U>, &str, &str, &[&str]|:'a -> IoResult<()>>,
    pub chanlists: HashMap<String, Vec<String>>,
}

impl<'a> IrcBot<'a, BufferedWriter<TcpStream>, TcpStream> {
    pub fn new(process: |&IrcBot<BufferedWriter<TcpStream>, TcpStream>, &str, &str, &[&str]|:'a -> IoResult<()>) -> IoResult<IrcBot<'a, BufferedWriter<TcpStream>, TcpStream>> {
        let config = try!(Config::load());
        let conn = try!(Connection::connect(config.server.as_slice(), config.port));
        Ok(IrcBot {
            conn: RefCell::new(conn),
            config: config,
            process: RefCell::new(process),
            chanlists: HashMap::new(),
        })
    }
}

impl<'a, T, U> Bot<'a> for IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    fn send_nick(&self, nick: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "NICK", [nick]))
    }

    fn send_user(&self, username: &str, real_name: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "USER", [username, "0", "*", real_name]))
    }

    fn send_join(&self, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "JOIN", [chan.as_slice()]))
    }

    fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "MODE", [chan.as_slice(), mode.as_slice()]))
    }

    fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "TOPIC", [chan.as_slice(), topic.as_slice()]))
    }

    fn send_invite(&self, person: &str, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "INVITE", [person.as_slice(), chan.as_slice()]))
    }

    fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PRIVMSG", [chan.as_slice(), msg.as_slice()]))
    }

    fn identify(&self) -> IoResult<()> {
        try!(self.send_nick(self.config.nickname.as_slice()));
        self.send_user(self.config.username.as_slice(), self.config.realname.as_slice())
    }

    fn output(&mut self) -> IoResult<()> {
        let mut reader = match self.conn.borrow_mut().deref_mut() {
            &Conn(_, ref recv) => BufferedReader::new(recv.clone()),
        };
        for line in reader.lines() {
            match line {
                Ok(ln) => {
                    let (source, command, args) = try!(process(ln.as_slice()));
                    try!(self.handle_command(source, command, args.as_slice()));
                    println!("{}", ln)
                },
                Err(e) => println!("Shit, you're fucked! {}", e),
            }
        }
        Ok(())
    }

    fn config(&self) -> &Config {
        &self.config
    }
}

impl<'a, T, U> IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    fn handle_command(&mut self, source: &str, command: &str, args: &[&str]) -> IoResult<()> {
        match (command, args) {
            ("PING", [msg]) => {
                try!(Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PONG", [msg])));
            },
            ("376", _) => { // End of MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("422", _) => { // Missing MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("353", [_, _, chan, users]) => { // /NAMES
                for user in users.split_str(" ") {
                    if !match self.chanlists.find_mut(&String::from_str(chan)) {
                        Some(vec) => {
                            vec.push(String::from_str(user));
                            true
                        },
                        None => false,
                    } {
                        self.chanlists.insert(String::from_str(chan), vec!(String::from_str(user)));
                    }
                }
            },
            ("JOIN", [chan]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => vec.push(String::from_str(source.slice_to(i))),
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            ("PART", [chan, _]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => {
                                match vec.as_slice().position_elem(&String::from_str(source.slice_to(i))) {
                                    Some(n) => {
                                        vec.swap_remove(n);
                                    },
                                    None => (),
                                };
                            },
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            _ => {
                try!((*self.process.borrow_mut().deref_mut())(self, source, command, args));
            },
        };
        Ok(())
    }
}

fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> {
    let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)");
    let cap = match reg.captures(msg) {
        Some(x) => x,
        None => return Err(IoError {
            kind: InvalidInput,
            desc: "Failed to parse line",
            detail: None,
        }),
    };
    let source = cap.at(1);
    let command = cap.at(2);
    let args = parse_args(cap.at(3));
    Ok((source, command, args))
}

fn parse_args(line: &str) -> Vec<&str> {
    let reg = regex!(r" ([^: ]+)| :([^\r\n]*)[\r\n]*$");
    reg.captures_iter(line).map(|cap| {
        match cap.at(1) {
            "" => cap.at(2),
            x => x,
        }
    }).collect()
}

#[test]
fn process_line_test() {
    let res = process(":flare.to.ca.fyrechat.net 353 pickles = #pickles :pickles awe\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "flare.to.ca.fyrechat.net");
    assert_eq!(command, "353");
    assert_eq!(args, vec!["pickles", "=", "#pickles", "pickles awe"]);

    let res = process("PING :flare.to.ca.fyrechat.net\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "");
    assert_eq!(command, "PING");
    assert_eq!(args, vec!["flare.to.ca.fyrechat.net"]);
}

#[test]
fn process_args_test() {
    let res = parse_args("PRIVMSG #vana :hi");
    assert_eq!(res, vec!["#vana", "hi"])
}
<commit_msg>Added from_connection(...) to make an IrcBot from any arbitrary connection.<commit_after>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate serialize;

use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream};
use std::vec::Vec;
use conn::{Conn, Connection};
use data::{Config, IrcReader, IrcWriter, Message};

pub mod conn;
pub mod data;

pub trait Bot<'a> {
    fn send_nick(&self, nick: &str) -> IoResult<()>;
    fn send_user(&self, username: &str, real_name: &str) -> IoResult<()>;
    fn send_join(&self, chan: &str) -> IoResult<()>;
    fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()>;
    fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()>;
    fn send_invite(&self, person: &str, chan: &str) -> IoResult<()>;
    fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()>;
    fn identify(&self) -> IoResult<()>;
    fn output(&mut self) -> IoResult<()>;
    fn config(&self) -> &Config;
}

pub struct IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub conn: RefCell<Connection<T, U>>,
    pub config: Config,
    process: RefCell<|&IrcBot<T, U>, &str, &str, &[&str]|:'a -> IoResult<()>>,
    pub chanlists: HashMap<String, Vec<String>>,
}

impl<'a> IrcBot<'a, BufferedWriter<TcpStream>, TcpStream> {
    pub fn new(process: |&IrcBot<BufferedWriter<TcpStream>, TcpStream>, &str, &str, &[&str]|:'a -> IoResult<()>) -> IoResult<IrcBot<'a, BufferedWriter<TcpStream>, TcpStream>> {
        let config = try!(Config::load());
        let conn = try!(Connection::connect(config.server.as_slice(), config.port));
        Ok(IrcBot {
            conn: RefCell::new(conn),
            config: config,
            process: RefCell::new(process),
            chanlists: HashMap::new(),
        })
    }
}

impl<'a, T, U> Bot<'a> for IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    fn send_nick(&self, nick: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "NICK", [nick]))
    }

    fn send_user(&self, username: &str, real_name: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "USER", [username, "0", "*", real_name]))
    }

    fn send_join(&self, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "JOIN", [chan.as_slice()]))
    }

    fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "MODE", [chan.as_slice(), mode.as_slice()]))
    }

    fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "TOPIC", [chan.as_slice(), topic.as_slice()]))
    }

    fn send_invite(&self, person: &str, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "INVITE", [person.as_slice(), chan.as_slice()]))
    }

    fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PRIVMSG", [chan.as_slice(), msg.as_slice()]))
    }

    fn identify(&self) -> IoResult<()> {
        try!(self.send_nick(self.config.nickname.as_slice()));
        self.send_user(self.config.username.as_slice(), self.config.realname.as_slice())
    }

    fn output(&mut self) -> IoResult<()> {
        let mut reader = match self.conn.borrow_mut().deref_mut() {
            &Conn(_, ref recv) => BufferedReader::new(recv.clone()),
        };
        for line in reader.lines() {
            match line {
                Ok(ln) => {
                    let (source, command, args) = try!(process(ln.as_slice()));
                    try!(self.handle_command(source, command, args.as_slice()));
                    println!("{}", ln)
                },
                Err(e) => println!("Shit, you're fucked! {}", e),
            }
        }
        Ok(())
    }

    fn config(&self) -> &Config {
        &self.config
    }
}

impl<'a, T, U> IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub fn from_connection(conn: Connection<T, U>, process: |&IrcBot<T, U>, &str, &str, &[&str]|:'a -> IoResult<()>) -> IoResult<IrcBot<'a, T, U>> {
        let config = try!(Config::load());
        Ok(IrcBot {
            conn: RefCell::new(conn),
            config: config,
            process: RefCell::new(process),
            chanlists: HashMap::new(),
        })
    }

    fn handle_command(&mut self, source: &str, command: &str, args: &[&str]) -> IoResult<()> {
        match (command, args) {
            ("PING", [msg]) => {
                try!(Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PONG", [msg])));
            },
            ("376", _) => { // End of MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("422", _) => { // Missing MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("353", [_, _, chan, users]) => { // /NAMES
                for user in users.split_str(" ") {
                    if !match self.chanlists.find_mut(&String::from_str(chan)) {
                        Some(vec) => {
                            vec.push(String::from_str(user));
                            true
                        },
                        None => false,
                    } {
                        self.chanlists.insert(String::from_str(chan), vec!(String::from_str(user)));
                    }
                }
            },
            ("JOIN", [chan]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => vec.push(String::from_str(source.slice_to(i))),
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            ("PART", [chan, _]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => {
                                match vec.as_slice().position_elem(&String::from_str(source.slice_to(i))) {
                                    Some(n) => {
                                        vec.swap_remove(n);
                                    },
                                    None => (),
                                };
                            },
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            _ => {
                try!((*self.process.borrow_mut().deref_mut())(self, source, command, args));
            },
        };
        Ok(())
    }
}

fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> {
    let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)");
    let cap = match reg.captures(msg) {
        Some(x) => x,
        None => return Err(IoError {
            kind: InvalidInput,
            desc: "Failed to parse line",
            detail: None,
        }),
    };
    let source = cap.at(1);
    let command = cap.at(2);
    let args = parse_args(cap.at(3));
    Ok((source, command, args))
}

fn parse_args(line: &str) -> Vec<&str> {
    let reg = regex!(r" ([^: ]+)| :([^\r\n]*)[\r\n]*$");
    reg.captures_iter(line).map(|cap| {
        match cap.at(1) {
            "" => cap.at(2),
            x => x,
        }
    }).collect()
}

#[test]
fn process_line_test() {
    let res = process(":flare.to.ca.fyrechat.net 353 pickles = #pickles :pickles awe\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "flare.to.ca.fyrechat.net");
    assert_eq!(command, "353");
    assert_eq!(args, vec!["pickles", "=", "#pickles", "pickles awe"]);

    let res = process("PING :flare.to.ca.fyrechat.net\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "");
    assert_eq!(command, "PING");
    assert_eq!(args, vec!["flare.to.ca.fyrechat.net"]);
}

#[test]
fn process_args_test() {
    let res = parse_args("PRIVMSG #vana :hi");
    assert_eq!(res, vec!["#vana", "hi"])
}
<|endoftext|>


<commit_before>#[test]
fn it_works() {
}
<commit_msg>Implement basic UTM conversion for WGS84<commit_after>//! Micro-library for converting from geodetic to UTM coordinates.

use std::f64::consts::PI;

pub struct Ellipsoid {
    a: f64,
    f: f64,
}

const WGS84: Ellipsoid = Ellipsoid {
    a: 6378137.0,
    f: 1.0 / 298.257222101,
};

/// Degrees.
pub struct Degrees(pub f64);

impl Degrees {
    /// Converts degreees to radians.
    ///
    /// # Examples
    ///
    /// ```
    /// use utm::Degrees;
    /// let radians = Degrees(180.0).as_radians();
    /// ```
    pub fn as_radians(&self) -> Radians {
        Radians(self.0 * PI / 180.0)
    }
}

/// Radians.
pub struct Radians(pub f64);

/// Convert a latitude and longitude to UTM coordinates using the WGS84 ellipsoid.
///
/// # Examples
///
/// ```
/// use utm::{to_utm_wgs84, Degrees};
/// let (northing, easting, meridian_convergence) = to_utm_wgs84(Degrees(40.62), Degrees(-123.45), 10);
/// ```
pub fn to_utm_wgs84(latitude: Degrees, longitude: Degrees, zone: u8) -> (f64, f64, f64) {
    let ellipsoid = WGS84;
    let latitude = latitude.as_radians().0;
    let longitude = longitude.as_radians().0;
    let long_origin = zone as f64 * 6.0 - 183.0;
    let e2 = 2.0 * ellipsoid.f - ellipsoid.f * ellipsoid.f;
    let ep2 = e2 / (1.0 - e2);

    let n = ellipsoid.a / (1.0 - e2 * latitude.sin() * latitude.sin()).sqrt();
    let t = latitude.tan() * latitude.tan();
    let c = ep2 * latitude.cos() * latitude.cos();
    let a = latitude.cos() * (longitude - (long_origin * PI / 180.0));

    let term1 = 1.0 - e2 / 4.0 - (3.0 * e2 * e2) / 64.0 - (5.0 * e2 * e2 * e2) / 256.0;
    let term2 = (3.0 * e2) / 8.0 + (3.0 * e2 * e2) / 32.0 + (45.0 * e2 * e2 * e2) / 1024.0;
    let term3 = (15.0 * e2 * e2) / 256.0 + (45.0 * e2 * e2 * e2) / 1024.0;
    let term4 = (35.0 * e2 * e2 * e2) / 3072.0;

    let m = ellipsoid.a *
            (term1 * latitude - term2 * (2.0 * latitude).sin() + term3 * (4.0 * latitude).sin() -
             term4 * (6.0 * latitude).sin());

    let x1 = ((1.0 - t + c) * a * a * a) / 6.0;
    let x2 = ((5.0 - 18.0 * t + t * t + 72.0 * c - 58.0 * ep2) * a * a * a * a * a) / 120.0;
    let x = 0.9996 * n * (a + x1 + x2);

    let y1 = (5.0 - t + 9.0 * c + 4.0 * c * c) * (a * a * a * a) / 24.0;
    let y2 = (61.0 - 58.0 * t + t * t + 600.0 * c - 330.0 * ep2) * (a * a * a * a * a * a) / 720.0;
    let y3 = (a * a) / 2.0 + y1 + y2;
    let y = 0.9996 * (m + n * latitude.tan() * y3);

    let northing = y;
    let easting = x + 500000.0;

    let meridian_convergence = meridian_convergence(northing, easting, WGS84);
    (northing, easting, meridian_convergence)
}

fn meridian_convergence(northing: f64, easting: f64, ellipsoid: Ellipsoid) -> f64 {
    let e2: f64 = 2.0 * ellipsoid.f - ellipsoid.f * ellipsoid.f;
    let e1 = (1.0 - (1.0 - e2).sqrt()) / (1.0 + (1.0 - e2).sqrt());
    let mu_const = ellipsoid.a * (1.0 - e2 / 4.0 - 3.0 * e2 * e2 / 64.0 - 5.0 * e2 * e2 * e2 / 256.0);

    let np = northing / 0.9996;
    let mu = np / mu_const;
    let foot_lat = footprint_latitude(e1, mu);

    let ep = (easting - 500000.0) / 0.9996;
    let n = ellipsoid.a / (1.0 - e2 * foot_lat.sin() * foot_lat.sin()).sqrt();
    let m = (ellipsoid.a * (1.0 - e2)) / (1.0 - e2 * foot_lat.sin() * foot_lat.sin()).powf(1.5);

    let conv1 = -(ep / n) * foot_lat.tan();
    let h30 = (ep / n).powi(3);
    let k28 = n / m;
    let k29 = k28 * k28;
    let j29 = foot_lat.tan() * foot_lat.tan();
    let conv2 = (foot_lat.tan() * h30 / 3.0) * (-2.0 * k29 + 3.0 * k28 + j29);
    conv1 + conv2
}

fn footprint_latitude(e1: f64, mu: f64) -> f64 {
    let term1 = 3.0 * e1 / 2.0 - 27.0 * e1 * e1 * e1 / 32.0;
    let term2 = 21.0 * e1 * e1 / 16.0 - 55.0 * e1 * e1 * e1 * e1 / 32.0;
    let term3 = 151.0 * e1 * e1 * e1 / 96.0;
    let term4 = 1097.0 * e1 * e1 * e1 * e1 / 512.0;

    mu + term1 * (2.0 * mu).sin() + term2 * (4.0 * mu).sin() + term3 * (6.0 * mu).sin() +
    term4 * (8.0 * mu).sin()
}

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

    #[test]
    fn reference() {
        let latitude = Degrees(60.9679875497);
        let longitude = Degrees(-149.119325194);
        let (northing, easting, meridan_convgergence) = to_utm_wgs84(latitude, longitude, 6);
        assert!((385273.02 - easting).abs() < 1e-2);
        assert!((6761077.20 - northing).abs() < 1e-2);
        assert!((0.0323 - meridan_convgergence).abs() < 1e-4);
    }
}
<|endoftext|>