<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

use std::sync::{Arc, Mutex};
use std::str::FromStr;
use std::net::SocketAddr;
use std::thread;

use tokio_core::reactor::{Core, Timeout};
use tokio_core::net::TcpStream;
use tokio_core::io;
use futures::{Future, future};

use jsonrpc::{MetaIoHandler, Value, Metadata};
use Server;
use MetaExtractor;
use RequestContext;

fn casual_server(socket_addr: &SocketAddr) -> Server {
    let mut io = MetaIoHandler::<()>::new();
    io.add_method("say_hello", |_params| {
        Ok(Value::String("hello".to_string()))
    });
    Server::new(socket_addr.clone(), Arc::new(io))
}

fn wait(millis: u64) {
    thread::sleep(::std::time::Duration::from_millis(millis));
}

#[test]
fn doc_test() {
    ::logger::init_log();

    let mut io = MetaIoHandler::<()>::new();
    io.add_method("say_hello", |_params| {
        Ok(Value::String("hello".to_string()))
    });
    let server = Server::new(SocketAddr::from_str("0.0.0.0:17770").unwrap(), Arc::new(io));
    thread::spawn(move || server.run().expect("Server must run with no issues"));
}

#[test]
fn doc_test_connect() {
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17775".parse().unwrap();
    let server = casual_server(&addr);
    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let mut core = Core::new().expect("Tokio Core should be created with no errors");
    let stream = TcpStream::connect(&addr, &core.handle());
    let result = core.run(stream);

    assert!(result.is_ok());
}

fn dummy_request(addr: &SocketAddr, data: &[u8]) -> Vec<u8> {
    let mut core = Core::new().expect("Tokio Core should be created with no errors");
    let mut buffer = vec![0u8; 1024];

    let stream = TcpStream::connect(addr, &core.handle())
        .and_then(|stream| {
            io::write_all(stream, data)
        })
        .and_then(|(stream, _)| {
            io::read(stream, &mut buffer)
        })
        .and_then(|(_, read_buf, len)| {
            future::ok(read_buf[0..len].to_vec())
        });
    let result = core.run(stream).expect("Core should run with no errors");

    result
}

fn dummy_request_str(addr: &SocketAddr, data: &[u8]) -> String {
    String::from_utf8(dummy_request(addr, data)).expect("String should be utf-8")
}

#[test]
fn doc_test_handle() {
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17780".parse().unwrap();
    let server = casual_server(&addr);
    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let result = dummy_request_str(
        &addr,
        b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n",
    );

    assert_eq!(
        result,
        "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
        "Response does not exactly much the expected response",
    );
}

#[derive(Clone)]
pub struct SocketMetadata {
    addr: SocketAddr,
}

impl Default for SocketMetadata {
    fn default() -> Self {
        SocketMetadata { addr: "0.0.0.0:0".parse().unwrap() }
    }
}

impl SocketMetadata {
    pub fn addr(&self) -> &SocketAddr {
        &self.addr
    }
}

impl Metadata for SocketMetadata { }

impl From<SocketAddr> for SocketMetadata {
    fn from(addr: SocketAddr) -> SocketMetadata {
        SocketMetadata { addr: addr }
    }
}

pub struct PeerMetaExtractor;

impl MetaExtractor<SocketMetadata> for PeerMetaExtractor {
    fn extract(&self, context: &RequestContext) -> SocketMetadata {
        context.peer_addr.into()
    }
}

fn meta_server(socket_addr: &SocketAddr) -> Server<SocketMetadata> {
    let mut io = MetaIoHandler::<SocketMetadata>::new();
    io.add_method_with_meta("say_hello", |_params, meta: SocketMetadata| {
        future::ok(Value::String(format!("hello, {}", meta.addr()))).boxed()
    });
    Server::new(socket_addr.clone(), Arc::new(io)).extractor(Arc::new(PeerMetaExtractor) as Arc<MetaExtractor<SocketMetadata>>)
}

#[test]
fn peer_meta() {
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17785".parse().unwrap();
    let server = meta_server(&addr);
    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let result = dummy_request_str(
        &addr,
        b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"
    );

    // contains random port, so just smoky comparing response length
    assert_eq!(
        59,
        result.len()
    );
}

#[derive(Default)]
pub struct PeerListMetaExtractor {
    peers: Mutex<Vec<SocketAddr>>,
}

impl MetaExtractor<SocketMetadata> for PeerListMetaExtractor {
    fn extract(&self, context: &RequestContext) -> SocketMetadata {
        trace!(target: "tcp", "extracting to peer list...");
        self.peers.lock().unwrap().push(context.peer_addr.clone());
        context.peer_addr.into()
    }
}

#[test]
fn message() {

    /// MASSIVE SETUP
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17790".parse().unwrap();
    let mut io = MetaIoHandler::<SocketMetadata>::new();
    io.add_method_with_meta("say_hello", |_params, _: SocketMetadata| {
        future::ok(Value::String("hello".to_owned())).boxed()
    });
    let peer_list = Arc::new(PeerListMetaExtractor::default());
    let server = Server::new(addr.clone(), Arc::new(io))
        .extractor(peer_list.clone() as Arc<MetaExtractor<SocketMetadata>>);
    let dispatcher = server.dispatcher();

    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let mut core = Core::new().expect("Tokio Core should be created with no errors");
    let timeout = Timeout::new(::std::time::Duration::from_millis(100), &core.handle())
        .expect("There should be a timeout produced in message test");
    let mut buffer = vec![0u8; 1024];
    let mut buffer2 = vec![0u8; 1024];
    let executed = Mutex::new(false);

    /// CLIENT RUN
    let stream = TcpStream::connect(&addr, &core.handle())
        .and_then(|stream| {
            future::ok(stream).join(timeout)
        })
        .and_then(|stream| {
            let peer_addr = peer_list.peers.lock().unwrap()[0].clone();
            dispatcher.push_message(
                &peer_addr,
                "ping".to_owned(),
            );
            trace!(target: "tcp", "Dispatched message for {}", peer_addr);
            future::ok(stream)
        })
        .and_then(|(stream, _)| {
            io::read(stream, &mut buffer)
        })
        .and_then(|(stream, read_buf, len)| {
            trace!(target: "tcp", "Read ping message");
            let ping_signal = read_buf[0..len].to_vec();

            assert_eq!(
                "ping\n",
                String::from_utf8(ping_signal).expect("String should be utf-8"),
                "Sent request does not match received by the peer",
            );
            // ensure tat the above assert was actually triggered
            *executed.lock().unwrap() = true;

            future::ok(stream)
        })
        .and_then(|stream| {
            // make request AFTER message dispatches
            let data = b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n";
            io::write_all(stream, &data[..])
        })
        .and_then(|(stream, _)| {
            io::read(stream, &mut buffer2)
        })
        .and_then(|(_, read_buf, len)| {
            trace!(target: "tcp", "Read response message");
            let response_signal = read_buf[0..len].to_vec();
            assert_eq!(
                "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
                String::from_utf8(response_signal).expect("String should be utf-8"),
                "Response does not match the expected handling",
            );
            future::ok(())
        });

    core.run(stream).expect("Should be the payload in message test");
    assert!(*executed.lock().unwrap());
}
<commit_msg>another execution check<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

use std::sync::{Arc, Mutex};
use std::str::FromStr;
use std::net::SocketAddr;
use std::thread;

use tokio_core::reactor::{Core, Timeout};
use tokio_core::net::TcpStream;
use tokio_core::io;
use futures::{Future, future};

use jsonrpc::{MetaIoHandler, Value, Metadata};
use Server;
use MetaExtractor;
use RequestContext;

fn casual_server(socket_addr: &SocketAddr) -> Server {
    let mut io = MetaIoHandler::<()>::new();
    io.add_method("say_hello", |_params| {
        Ok(Value::String("hello".to_string()))
    });
    Server::new(socket_addr.clone(), Arc::new(io))
}

fn wait(millis: u64) {
    thread::sleep(::std::time::Duration::from_millis(millis));
}

#[test]
fn doc_test() {
    ::logger::init_log();

    let mut io = MetaIoHandler::<()>::new();
    io.add_method("say_hello", |_params| {
        Ok(Value::String("hello".to_string()))
    });
    let server = Server::new(SocketAddr::from_str("0.0.0.0:17770").unwrap(), Arc::new(io));
    thread::spawn(move || server.run().expect("Server must run with no issues"));
}

#[test]
fn doc_test_connect() {
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17775".parse().unwrap();
    let server = casual_server(&addr);
    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let mut core = Core::new().expect("Tokio Core should be created with no errors");
    let stream = TcpStream::connect(&addr, &core.handle());
    let result = core.run(stream);

    assert!(result.is_ok());
}

fn dummy_request(addr: &SocketAddr, data: &[u8]) -> Vec<u8> {
    let mut core = Core::new().expect("Tokio Core should be created with no errors");
    let mut buffer = vec![0u8; 1024];

    let stream = TcpStream::connect(addr, &core.handle())
        .and_then(|stream| {
            io::write_all(stream, data)
        })
        .and_then(|(stream, _)| {
            io::read(stream, &mut buffer)
        })
        .and_then(|(_, read_buf, len)| {
            future::ok(read_buf[0..len].to_vec())
        });
    let result = core.run(stream).expect("Core should run with no errors");

    result
}

fn dummy_request_str(addr: &SocketAddr, data: &[u8]) -> String {
    String::from_utf8(dummy_request(addr, data)).expect("String should be utf-8")
}

#[test]
fn doc_test_handle() {
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17780".parse().unwrap();
    let server = casual_server(&addr);
    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let result = dummy_request_str(
        &addr,
        b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n",
    );

    assert_eq!(
        result,
        "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
        "Response does not exactly much the expected response",
    );
}

#[derive(Clone)]
pub struct SocketMetadata {
    addr: SocketAddr,
}

impl Default for SocketMetadata {
    fn default() -> Self {
        SocketMetadata { addr: "0.0.0.0:0".parse().unwrap() }
    }
}

impl SocketMetadata {
    pub fn addr(&self) -> &SocketAddr {
        &self.addr
    }
}

impl Metadata for SocketMetadata { }

impl From<SocketAddr> for SocketMetadata {
    fn from(addr: SocketAddr) -> SocketMetadata {
        SocketMetadata { addr: addr }
    }
}

pub struct PeerMetaExtractor;

impl MetaExtractor<SocketMetadata> for PeerMetaExtractor {
    fn extract(&self, context: &RequestContext) -> SocketMetadata {
        context.peer_addr.into()
    }
}

fn meta_server(socket_addr: &SocketAddr) -> Server<SocketMetadata> {
    let mut io = MetaIoHandler::<SocketMetadata>::new();
    io.add_method_with_meta("say_hello", |_params, meta: SocketMetadata| {
        future::ok(Value::String(format!("hello, {}", meta.addr()))).boxed()
    });
    Server::new(socket_addr.clone(), Arc::new(io)).extractor(Arc::new(PeerMetaExtractor) as Arc<MetaExtractor<SocketMetadata>>)
}

#[test]
fn peer_meta() {
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17785".parse().unwrap();
    let server = meta_server(&addr);
    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let result = dummy_request_str(
        &addr,
        b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"
    );

    // contains random port, so just smoky comparing response length
    assert_eq!(
        59,
        result.len()
    );
}

#[derive(Default)]
pub struct PeerListMetaExtractor {
    peers: Mutex<Vec<SocketAddr>>,
}

impl MetaExtractor<SocketMetadata> for PeerListMetaExtractor {
    fn extract(&self, context: &RequestContext) -> SocketMetadata {
        trace!(target: "tcp", "extracting to peer list...");
        self.peers.lock().unwrap().push(context.peer_addr.clone());
        context.peer_addr.into()
    }
}

#[test]
fn message() {

    /// MASSIVE SETUP
    ::logger::init_log();
    let addr: SocketAddr = "127.0.0.1:17790".parse().unwrap();
    let mut io = MetaIoHandler::<SocketMetadata>::new();
    io.add_method_with_meta("say_hello", |_params, _: SocketMetadata| {
        future::ok(Value::String("hello".to_owned())).boxed()
    });
    let peer_list = Arc::new(PeerListMetaExtractor::default());
    let server = Server::new(addr.clone(), Arc::new(io))
        .extractor(peer_list.clone() as Arc<MetaExtractor<SocketMetadata>>);
    let dispatcher = server.dispatcher();

    thread::spawn(move || server.run().expect("Server must run with no issues"));
    wait(100);

    let mut core = Core::new().expect("Tokio Core should be created with no errors");
    let timeout = Timeout::new(::std::time::Duration::from_millis(100), &core.handle())
        .expect("There should be a timeout produced in message test");
    let mut buffer = vec![0u8; 1024];
    let mut buffer2 = vec![0u8; 1024];
    let executed_dispatch = Mutex::new(false);
    let executed_request = Mutex::new(false);

    /// CLIENT RUN
    let stream = TcpStream::connect(&addr, &core.handle())
        .and_then(|stream| {
            future::ok(stream).join(timeout)
        })
        .and_then(|stream| {
            let peer_addr = peer_list.peers.lock().unwrap()[0].clone();
            dispatcher.push_message(
                &peer_addr,
                "ping".to_owned(),
            );
            trace!(target: "tcp", "Dispatched message for {}", peer_addr);
            future::ok(stream)
        })
        .and_then(|(stream, _)| {
            io::read(stream, &mut buffer)
        })
        .and_then(|(stream, read_buf, len)| {
            trace!(target: "tcp", "Read ping message");
            let ping_signal = read_buf[0..len].to_vec();

            assert_eq!(
                "ping\n",
                String::from_utf8(ping_signal).expect("String should be utf-8"),
                "Sent request does not match received by the peer",
            );
            // ensure tat the above assert was actually triggered
            *executed_dispatch.lock().unwrap() = true;

            future::ok(stream)
        })
        .and_then(|stream| {
            // make request AFTER message dispatches
            let data = b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n";
            io::write_all(stream, &data[..])
        })
        .and_then(|(stream, _)| {
            io::read(stream, &mut buffer2)
        })
        .and_then(|(_, read_buf, len)| {
            trace!(target: "tcp", "Read response message");
            let response_signal = read_buf[0..len].to_vec();
            assert_eq!(
                "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
                String::from_utf8(response_signal).expect("String should be utf-8"),
                "Response does not match the expected handling",
            );
            *executed_request.lock().unwrap() = true;

            future::ok(())
        });

    core.run(stream).expect("Should be the payload in message test");
    assert!(*executed_dispatch.lock().unwrap());
    assert!(*executed_request.lock().unwrap());
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

#[macro_use]
extern crate log;
extern crate hayaku_http;
#[macro_use(quick_error)]
extern crate quick_error;
extern crate regex;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

mod error;
mod trie;

use hayaku_http::{Handler, Method, Request, RequestHandler, Response, Status};

use std::collections::HashMap;

pub use error::Error;

use trie::TrieNode;

type Tree<T> = HashMap<Method, TrieNode<RequestHandler<T>>>;

#[derive(Clone)]
pub struct Router<T: Clone> {
    trees: Tree<T>,
    /// Enables automatic redirection if the current route can't be matched but
    /// a handler for the path with (without) the trailing slash exists.
    /// For example if /foo/ is requested but a route only exists for /foo, the
    /// client is redirected to /foo with http status code 301 for GET requests
    /// and 307 for all other request methods.
    pub redirect_trailing_slash: bool,
    /// If enabled, the router tries to fix the current request path, if no
    /// handle is registered for it.
    /// First superfluous path elements like ../ or // are removed.
    /// Afterwards the router does a case-insensitive lookup of the cleaned path.
    /// If a handle can be found for this route, the router makes a redirection
    /// to the corrected path with status code 301 for GET requests and 307 for
    /// all other request methods.
    /// For example /FOO and /..//Foo could be redirected to /foo.
    /// `redirect_trailing_slash` is independent of this option.
    pub redirect_fixed_path: bool,
    /// If enabled, the router checks if another method is allowed for the
    /// current route, if the current request can not be routed.
    /// If this is the case, the request is answered with `Method Not Allowed`
    /// and HTTP status code 405.
    /// If no other Method is allowed, the request is delegated to the NotFound
    /// handler.
    pub handle_method_not_allowed: bool,
    /// If enabled, the router automatically replies to OPTIONS requests.
    /// Custom OPTIONS handlers take priority over automatic replies.
    pub handle_options: bool,
    /// Configurable handler which is called when no matching route is
    /// found. If it is `None`, the default 404 handler is used.
    not_found: Option<RequestHandler<T>>,
}

impl<T: Clone> Router<T> {
    pub fn new() -> Self {
        Router {
            trees: HashMap::new(),
            redirect_trailing_slash: true,
            redirect_fixed_path: true,
            handle_method_not_allowed: true,
            handle_options: true,
            not_found: None,
        }
    }

    pub fn set_not_found_handler(&mut self, handler: RequestHandler<T>) {
        self.not_found = Some(handler);
    }

    /// `get` is a shortcut for `Self::handle(Method::Get, path, handle)`.
    pub fn get<S: Into<String>>(&mut self,
                                path: S,
                                handle: RequestHandler<T>)
                                -> Result<(), Error> {
        self.handle(Method::Get, path, handle)
    }

    /// `head` is a shortcut for `Self::handle(Method::Head, path, handle)`.
    pub fn head<S: Into<String>>(&mut self,
                                 path: S,
                                 handle: RequestHandler<T>)
                                 -> Result<(), Error> {
        self.handle(Method::Head, path, handle)
    }

    /// `options` is a shortcut for `Self::handle(Method::Options, path, handle)`.
    pub fn options<S: Into<String>>(&mut self,
                                    path: S,
                                    handle: RequestHandler<T>)
                                    -> Result<(), Error> {
        self.handle(Method::Options, path, handle)
    }

    /// `post` is a shortcut for `Self::handle(Method::Post, path, handle)`.
    pub fn post<S: Into<String>>(&mut self,
                                 path: S,
                                 handle: RequestHandler<T>)
                                 -> Result<(), Error> {
        self.handle(Method::Post, path, handle)
    }

    /// `put` is a shortcut for `Self::handle(Method::Put, path, handle)`.
    pub fn put<S: Into<String>>(&mut self,
                                path: S,
                                handle: RequestHandler<T>)
                                -> Result<(), Error> {
        self.handle(Method::Put, path, handle)
    }

    /// `patch` is a shortcut for `Self::handle(Method::Patch, path, handle)`.
    pub fn patch<S: Into<String>>(&mut self,
                                  path: S,
                                  handle: RequestHandler<T>)
                                  -> Result<(), Error> {
        self.handle(Method::Patch, path, handle)
    }

    /// `delete` is a shortcut for `Self::handle(Method::Delete, path, handle)`.
    pub fn delete<S: Into<String>>(&mut self,
                                   path: S,
                                   handle: RequestHandler<T>)
                                   -> Result<(), Error> {
        self.handle(Method::Delete, path, handle)
    }

    /// Registers a new request handle with the given path and method.
    ///
    /// For GET, POST, PUT, PATCH, and DELETE requests the respective
    /// shortcut functions can be used.
    ///
    /// This function is intended for bulk loading and to allow the usage
    /// of less frequently used, non-standardized or custom methods
    /// (e.g. for internal communication with a proxy).
    pub fn handle<S: Into<String>>(&mut self,
                                   method: Method,
                                   path: S,
                                   handle: RequestHandler<T>)
                                   -> Result<(), Error> {
        let path = path.into();
        if !path.starts_with('/') {
            return Err(Error::StartWithSlash(path.to_string()));
        }

        if self.trees.get(&method).is_none() {
            let root = TrieNode::new();
            self.trees.insert(method.clone(), root);
        }

        // TODO(nokaa): we should probably not unwrap here.
        // It may be possible for the retrieval to fail, even
        // though we check just before this.
        let mut root = self.trees.get_mut(&method).unwrap();
        root.insert(path, handle);

        Ok(())
    }
}

impl<T: Clone> Handler<T> for Router<T> {
    // Handler makes the router implement the fasthttp.ListenAndServe interface.
    fn handler(&self, req: &Request, res: &mut Response, ctx: &T) {
        let path = {
            let path = req.path().unwrap();
            let data_loc = path.find('?').unwrap_or(path.len());
            &path[..data_loc]
        };
        debug!("path: {}", path);
        let method = req.method().clone();
        debug!("method: {:?}", method);
        if let Some(root) = self.trees.get(&method) {
            match root.get(&path) {
                Some((val, map)) => {
                    let serialized = serde_json::to_vec(&map).unwrap();
                    *req.user_data.borrow_mut() = serialized;
                    val.unwrap()(req, res, ctx);
                }
                None => {
                    if self.not_found.is_none() {
                        // Default handler
                        res.status(Status::NotFound);
                        let msg = String::from("404, path \"") + &path + "\" not found :(";
                        res.body(msg.into_bytes())
                    } else {
                        // We have already checked that self.not_found is not
                        // `None`, so unwrapping should be okay.
                        let handle = self.not_found.clone().unwrap();
                        handle(req, res, ctx);
                    }
                }
            }
        } else {
            // TODO(nokaa): We want to send a different error than 404
            // for this case. In this case we have an incorrect method being
            // used.
            if self.not_found.is_none() {
                // Default handler
                res.status(Status::NotFound);
                let msg = String::from("404, path \"") + &path + "\" not found :(";
                res.body(msg.into_bytes());
            } else {
                // We have already checked that self.not_found is not
                // `None`, so unwrapping should be okay.
                let handle = self.not_found.clone().unwrap();
                handle(req, res, ctx);
            }
        }
    }
}
<commit_msg>Update for httbloat<commit_after>#![feature(proc_macro)]

#[macro_use]
extern crate log;
extern crate hayaku_http;
#[macro_use(quick_error)]
extern crate quick_error;
extern crate regex;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

mod error;
mod trie;

use hayaku_http::{Handler, Method, Request, RequestHandler, Response, Status};

use std::collections::HashMap;

pub use error::Error;

use trie::TrieNode;

type Tree<T> = HashMap<Method, TrieNode<RequestHandler<T>>>;

#[derive(Clone)]
pub struct Router<T: Clone> {
    trees: Tree<T>,
    /// Enables automatic redirection if the current route can't be matched but
    /// a handler for the path with (without) the trailing slash exists.
    /// For example if /foo/ is requested but a route only exists for /foo, the
    /// client is redirected to /foo with http status code 301 for GET requests
    /// and 307 for all other request methods.
    pub redirect_trailing_slash: bool,
    /// If enabled, the router tries to fix the current request path, if no
    /// handle is registered for it.
    /// First superfluous path elements like ../ or // are removed.
    /// Afterwards the router does a case-insensitive lookup of the cleaned path.
    /// If a handle can be found for this route, the router makes a redirection
    /// to the corrected path with status code 301 for GET requests and 307 for
    /// all other request methods.
    /// For example /FOO and /..//Foo could be redirected to /foo.
    /// `redirect_trailing_slash` is independent of this option.
    pub redirect_fixed_path: bool,
    /// If enabled, the router checks if another method is allowed for the
    /// current route, if the current request can not be routed.
    /// If this is the case, the request is answered with `Method Not Allowed`
    /// and HTTP status code 405.
    /// If no other Method is allowed, the request is delegated to the NotFound
    /// handler.
    pub handle_method_not_allowed: bool,
    /// If enabled, the router automatically replies to OPTIONS requests.
    /// Custom OPTIONS handlers take priority over automatic replies.
    pub handle_options: bool,
    /// Configurable handler which is called when no matching route is
    /// found. If it is `None`, the default 404 handler is used.
    not_found: Option<RequestHandler<T>>,
}

impl<T: Clone> Router<T> {
    pub fn new() -> Self {
        Router {
            trees: HashMap::new(),
            redirect_trailing_slash: true,
            redirect_fixed_path: true,
            handle_method_not_allowed: true,
            handle_options: true,
            not_found: None,
        }
    }

    pub fn set_not_found_handler(&mut self, handler: RequestHandler<T>) {
        self.not_found = Some(handler);
    }

    /// `get` is a shortcut for `Self::handle(Method::Get, path, handle)`.
    pub fn get<S: Into<String>>(&mut self,
                                path: S,
                                handle: RequestHandler<T>)
                                -> Result<(), Error> {
        self.handle(Method::Get, path, handle)
    }

    /// `head` is a shortcut for `Self::handle(Method::Head, path, handle)`.
    pub fn head<S: Into<String>>(&mut self,
                                 path: S,
                                 handle: RequestHandler<T>)
                                 -> Result<(), Error> {
        self.handle(Method::Head, path, handle)
    }

    /// `options` is a shortcut for `Self::handle(Method::Options, path, handle)`.
    pub fn options<S: Into<String>>(&mut self,
                                    path: S,
                                    handle: RequestHandler<T>)
                                    -> Result<(), Error> {
        self.handle(Method::Options, path, handle)
    }

    /// `post` is a shortcut for `Self::handle(Method::Post, path, handle)`.
    pub fn post<S: Into<String>>(&mut self,
                                 path: S,
                                 handle: RequestHandler<T>)
                                 -> Result<(), Error> {
        self.handle(Method::Post, path, handle)
    }

    /// `put` is a shortcut for `Self::handle(Method::Put, path, handle)`.
    pub fn put<S: Into<String>>(&mut self,
                                path: S,
                                handle: RequestHandler<T>)
                                -> Result<(), Error> {
        self.handle(Method::Put, path, handle)
    }

    /// `patch` is a shortcut for `Self::handle(Method::Patch, path, handle)`.
    pub fn patch<S: Into<String>>(&mut self,
                                  path: S,
                                  handle: RequestHandler<T>)
                                  -> Result<(), Error> {
        self.handle(Method::Patch, path, handle)
    }

    /// `delete` is a shortcut for `Self::handle(Method::Delete, path, handle)`.
    pub fn delete<S: Into<String>>(&mut self,
                                   path: S,
                                   handle: RequestHandler<T>)
                                   -> Result<(), Error> {
        self.handle(Method::Delete, path, handle)
    }

    /// Registers a new request handle with the given path and method.
    ///
    /// For GET, POST, PUT, PATCH, and DELETE requests the respective
    /// shortcut functions can be used.
    ///
    /// This function is intended for bulk loading and to allow the usage
    /// of less frequently used, non-standardized or custom methods
    /// (e.g. for internal communication with a proxy).
    pub fn handle<S: Into<String>>(&mut self,
                                   method: Method,
                                   path: S,
                                   handle: RequestHandler<T>)
                                   -> Result<(), Error> {
        let path = path.into();
        if !path.starts_with('/') {
            return Err(Error::StartWithSlash(path.to_string()));
        }

        if self.trees.get(&method).is_none() {
            let root = TrieNode::new();
            self.trees.insert(method.clone(), root);
        }

        // TODO(nokaa): we should probably not unwrap here.
        // It may be possible for the retrieval to fail, even
        // though we check just before this.
        let mut root = self.trees.get_mut(&method).unwrap();
        root.insert(path, handle);

        Ok(())
    }
}

impl<T: Clone> Handler<T> for Router<T> {
    // Handler makes the router implement the fasthttp.ListenAndServe interface.
    fn handler(&self, req: &Request, res: &mut Response, ctx: &T) {
        let path = req.path();
        let path = {
            let data_loc = path.find('?').unwrap_or(path.len());
            &path[..data_loc]
        };
        debug!("path: {}", path);
        let method = req.method().clone();
        debug!("method: {:?}", method);
        if let Some(root) = self.trees.get(&method) {
            match root.get(&path) {
                Some((val, map)) => {
                    let serialized = serde_json::to_vec(&map).unwrap();
                    *req.user_data.borrow_mut() = serialized;
                    val.unwrap()(req, res, ctx);
                }
                None => {
                    if self.not_found.is_none() {
                        // Default handler
                        res.status(Status::NotFound);
                        let msg = String::from("404, path \"") + &path + "\" not found :(";
                        res.body(&msg.into_bytes());
                    } else {
                        // We have already checked that self.not_found is not
                        // `None`, so unwrapping should be okay.
                        let handle = self.not_found.clone().unwrap();
                        handle(req, res, ctx);
                    }
                }
            }
        } else {
            // TODO(nokaa): We want to send a different error than 404
            // for this case. In this case we have an incorrect method being
            // used.
            if self.not_found.is_none() {
                // Default handler
                res.status(Status::NotFound);
                let msg = String::from("404, path \"") + &path + "\" not found :(";
                res.body(&msg.into_bytes());
            } else {
                // We have already checked that self.not_found is not
                // `None`, so unwrapping should be okay.
                let handle = self.not_found.clone().unwrap();
                handle(req, res, ctx);
            }
        }
    }
}
<|endoftext|>


<commit_before>#![recursion_limit = "1024"]
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[macro_use]
extern crate error_chain;

use std::io::{self, Read, BufRead};
use std::str::{self, FromStr};

mod errors {
    error_chain!{}
}

use errors::*;

pub struct InputStream<T: BufRead> {
    reader: T,
    byte_buffer: Vec<u8>,
}

fn is_whitespace(c: u8) -> bool {
    match c {
        b' ' |
        b'\x09'...b'\x0d' => true,
        _ => false,
    }
}

fn act_while<T, F, G>(reader: &mut T, mut condition: F, mut act: G) -> io::Result<()>
    where T: BufRead,
          F: FnMut(&&u8) -> bool,
          G: FnMut(&[u8])
{
    loop {
        let (skipped, done) = match reader.fill_buf() {
            Ok(buf) => {
                let skipped = buf.iter().take_while(&mut condition).count();
                act(&buf[..skipped]);
                (skipped, skipped < buf.len() || buf.len() == 0)
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };

        reader.consume(skipped);
        if done {
            break;
        }
    }
    Ok(())
}

fn scan<T, F>(reader: &mut T, byte_buffer: &mut Vec<u8>) -> Result<F>
    where T: BufRead,
          F: FromStr,
          <F as FromStr>::Err: std::error::Error + Send + 'static
{
    act_while(reader, |&&c| is_whitespace(c), |_| {}).chain_err(|| "IO Error")?;
    byte_buffer.clear();
    act_while(reader,
              |&&c| !is_whitespace(c),
              |slice| byte_buffer.extend_from_slice(slice)).chain_err(|| "IO Error")?;

    let slice = match byte_buffer.split_last() {
        Some((&b' ', slice)) => slice,
        _ => byte_buffer.as_slice(),
    };

    str::from_utf8(slice)
        .chain_err(|| "Input data not Utf-8")?
        .parse::<F>()
        .chain_err(|| "Could not parse string into requested type")
}

impl<T: BufRead> InputStream<T> {
    pub fn new(reader: T) -> InputStream<T> {
        InputStream {
            reader: reader,
            byte_buffer: Vec::new(),
        }
    }

    pub fn scan<F>(&mut self) -> Result<F>
        where F: FromStr,
              <F as FromStr>::Err: std::error::Error + Send + 'static
    {
        scan(&mut self.reader, &mut self.byte_buffer)
    }
}

impl<T: BufRead> Read for InputStream<T> {
    fn read(&mut self, buffer: &mut [u8]) -> std::io::Result<usize> {
        self.reader.read(buffer)
    }
}

impl<T: BufRead> BufRead for InputStream<T> {
    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
        self.reader.fill_buf()
    }

    fn consume(&mut self, amount: usize) {
        self.reader.consume(amount)
    }
}

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

    #[test]
    fn simple_strings() {
        let text = "Howdy neighbour, how are you doing?";
        let mut stream = InputStream::new(text.as_bytes());

        let first: String = stream.scan().unwrap();
        let second: String = stream.scan().unwrap();
        let third: String = stream.scan().unwrap();
        assert_eq!(first, "Howdy");
        assert_eq!(second, "neighbour,");
        assert_eq!(third, "how");
    }

    #[test]
    fn simple_numbers() {
        let text = "5 -7 12.5 -2.85";
        let mut stream = InputStream::new(text.as_bytes());
        assert_eq!(5, stream.scan().unwrap());
        assert_eq!(-7, stream.scan().unwrap());
        assert_eq!(12.5, stream.scan().unwrap());
        assert_eq!(-2.85, stream.scan().unwrap());
    }

    #[test]
    fn newlines() {
        let mut stream = InputStream::new("12\nHello".as_bytes());
        assert_eq!(12, stream.scan().unwrap());
        assert_eq!("Hello", stream.scan::<String>().unwrap());
    }
}
<commit_msg>Reorganized the code a bit<commit_after>#![recursion_limit = "1024"]
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[macro_use]
extern crate error_chain;

use std::io::{self, Read, BufRead};
use std::str::{self, FromStr};

mod errors {
    error_chain!{}
}

use errors::*;

pub struct InputStream<T: BufRead> {
    reader: T,
    byte_buffer: Vec<u8>,
}

fn is_whitespace(c: u8) -> bool {
    match c {
        b' ' |
        b'\x09'...b'\x0d' => true,
        _ => false,
    }
}

fn act_while<T, F, G>(reader: &mut T, mut condition: F, mut act: G) -> io::Result<()>
    where T: BufRead,
          F: FnMut(&&u8) -> bool,
          G: FnMut(&[u8])
{
    loop {
        let (skipped, done) = match reader.fill_buf() {
            Ok(buf) => {
                let skipped = buf.iter().take_while(&mut condition).count();
                act(&buf[..skipped]);
                (skipped, skipped < buf.len() || buf.len() == 0)
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };

        reader.consume(skipped);
        if done {
            break;
        }
    }
    Ok(())
}

impl<T: BufRead> InputStream<T> {
    pub fn new(reader: T) -> InputStream<T> {
        InputStream {
            reader: reader,
            byte_buffer: Vec::new(),
        }
    }

    pub fn scan<F>(&mut self) -> Result<F>
        where F: FromStr,
              <F as FromStr>::Err: std::error::Error + Send + 'static
    {
        let &mut InputStream { ref mut reader, ref mut byte_buffer } = self;
        act_while(reader, |&&c| is_whitespace(c), |_| {}).chain_err(|| "IO Error")?;
        byte_buffer.clear();
        act_while(reader,
                  |&&c| !is_whitespace(c),
                  |slice| byte_buffer.extend_from_slice(slice)).chain_err(|| "IO Error")?;

        let slice = match byte_buffer.split_last() {
            Some((&b' ', slice)) => slice,
            _ => byte_buffer.as_slice(),
        };

        str::from_utf8(slice)
            .chain_err(|| "Input data not Utf-8")?
            .parse::<F>()
            .chain_err(|| "Could not parse string into requested type")
    }
}

impl<T: BufRead> Read for InputStream<T> {
    fn read(&mut self, buffer: &mut [u8]) -> std::io::Result<usize> {
        self.reader.read(buffer)
    }
}

impl<T: BufRead> BufRead for InputStream<T> {
    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
        self.reader.fill_buf()
    }

    fn consume(&mut self, amount: usize) {
        self.reader.consume(amount)
    }
}

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

    #[test]
    fn simple_strings() {
        let text = "Howdy neighbour, how are you doing?";
        let mut stream = InputStream::new(text.as_bytes());

        let first: String = stream.scan().unwrap();
        let second: String = stream.scan().unwrap();
        let third: String = stream.scan().unwrap();
        assert_eq!(first, "Howdy");
        assert_eq!(second, "neighbour,");
        assert_eq!(third, "how");
    }

    #[test]
    fn simple_numbers() {
        let text = "5 -7 12.5 -2.85";
        let mut stream = InputStream::new(text.as_bytes());
        assert_eq!(5, stream.scan().unwrap());
        assert_eq!(-7, stream.scan().unwrap());
        assert_eq!(12.5, stream.scan().unwrap());
        assert_eq!(-2.85, stream.scan().unwrap());
    }

    #[test]
    fn newlines() {
        let mut stream = InputStream::new("12\nHello".as_bytes());
        assert_eq!(12, stream.scan().unwrap());
        assert_eq!("Hello", stream.scan::<String>().unwrap());
    }
}
<|endoftext|>


<commit_before>//! An outline of how linear types could be combined with JS-managed data
//!
//! The idea is to use the JS context as a linear token.
//! Each JS context gets its own type `Cx` which implements the `JSContext` trait.
//! Access to read-only JS-managed data requires a context of type `&Cx`.
//! Access to read-write JS-managed data requires a context of type `&mut Cx`.
//! Linear use of the context ensures that Rust's memory safety is preserved (er, I hope).
//!
//! This API doesn't address tracing, which would have to be handled similarly
//! to servo's current JS bindings.
//!
//! One thing that makes this easier is that we can arrange for any
//! calls into the JS engine which might trigger GC to take a `&mut Cx`
//! argument, which gives us control of when GC might occur.

use std::marker::PhantomData;

/// The trait for native JS-manageable data.
pub unsafe trait JSManageable<'a> {
    /// This type should have the same mnemory represention as `Self`.
    /// The only difference between `Self` and `Self::ChangeLifetime`
    /// is that any `JSManaged<'b, Cx, T>` should be replaced by
    /// `JSManaged<'a, Cx, T::ChangeLifetime>`.
    type ChangeLifetime: 'a;
}

/// The trait for accessing JS-managed data.
pub trait JSAccess<Cx>: Sized {
    /// Read-only access to native JS-managed data.
    fn get<'a, 'b:'a, T>(&'a self, managed: JSManaged<'b, Cx, T>) -> &'a T::ChangeLifetime where
        T: JSManageable<'a>;

    /// Read-write access to native JS-managed data.
    fn get_mut<'a, 'b:'a, T>(&'a mut self, managed: JSManaged<'b, Cx, T>) -> &'a mut T::ChangeLifetime where
        T: JSManageable<'a>;
}

/// The trait for JS contexts.
pub trait JSContext: JSAccess<Self> {
    /// Get a snapshot of the JS state.
    /// The snapshot only allows access to the methods that are guaranteed not to call GC,
    /// so we don't need to root JS-managed pointers during the lifetime of a snapshot.
    fn snapshot(&mut self) -> JSSnapshot<Self>;

    /// Give ownership of data to JS.
    /// This allocates JS heap, which may trigger GC.
    fn manage<'a, T>(&'a self, value: T) -> JSManaged<'a, Self, T>
        where T: 'a + JSManageable<'a, ChangeLifetime=T>;

    // A real implementation would also have JS methods such as those in jsapi.
}

/// A placholder for the real `JSTraceable`.
pub unsafe trait JSTraceable<Cx> {}

/// A user of a JS context implements `JSContextConsumer`, which is called back
/// with a fresh JS context.
pub trait JSContextConsumer<T> {
    /// This callback is called with a fresh JS context.
    fn consume<Cx>(self, cx: &mut Cx) -> T where Cx: JSContext;
}

/// To create a fresh JS context, the user implements `JSContextConsumer`
/// for their type `K`, builds a `k:K`, then calls `with_js_context(k)`.
/// ```rust
///   struct MyConsumer;
///   impl JSContextConsumer<()> for MyConsumer {
///      fn consume<Cx: JSContext>(cx: Cx) {
///         // Do stuff with the JS context cx.
///      }
///   }
///   with_js_context(MyConsumer);
/// ```
pub fn with_js_context<C, T>(consumer: C) -> T where
    C: JSContextConsumer<T>
{
    // A real implementation would allocate a JS context
    let mut cx = JSContextImpl {};
    consumer.consume(&mut cx)
}

/// The type of JS-managed data in a JS context `Cx`.
///
/// If the user has access to a `&JSManaged`, then the JS-managed
/// data is live for the lifetime of the reference. In particular,
/// this means that there should never be any stack-allocated
/// `JSManaged` values, since they would allow the user to construct
/// `&JSManaged` references with arbitrary lifetimes.
pub struct JSManaged<'a, Cx, T> {
    // JS reflector goes here
    raw: *mut T,
    marker: PhantomData<(&'a(),Cx)>,
}

impl<'a, Cx, T> Clone for JSManaged<'a, Cx, T> {
    fn clone(&self) -> Self {
        JSManaged {
            raw: self.raw,
            marker: self.marker,
        }
    }
}

impl<'a, Cx, T> Copy for JSManaged<'a, Cx, T> {
}

unsafe impl<'a, 'b, Cx, T> JSManageable<'b> for JSManaged<'a, Cx, T> where
    Cx: 'b,
    T: JSManageable<'b>,
{
    type ChangeLifetime = JSManaged<'b, Cx, T::ChangeLifetime>;
}

impl<'a, Cx, T> JSManaged<'a, Cx, T> {
    /// Convenience method for `access.get(self)`.
    pub fn get<'b, Access: JSAccess<Cx>>(self, access: &'b Access) -> &'b T::ChangeLifetime where
        T: JSManageable<'b>,
        'a: 'b,
    {
        access.get::<'b, 'b, T>(self)
    }

    /// Convenience method for `access.get_mut(self)`.
    pub fn get_mut<'b, Access: JSAccess<Cx>>(self, access: &'b mut Access) -> &'b mut T::ChangeLifetime where
        T: JSManageable<'b>,
        'a: 'b,
    {
        access.get_mut(self)
    }

    /// Convenience method for `snapshot.extend_lifetime(self)`.
    pub fn extend_lifetime<'b>(self, snapshot: &JSSnapshot<'b, Cx>) -> JSManaged<'b, Cx, T::ChangeLifetime> where
        Cx: JSContext,
        T: JSManageable<'b>,
    {
        snapshot.extend_lifetime(self)
    }
}

/// A root set.
pub struct JSRoots<Cx> {
    // The real thing would contain a set of rooted JS objects.
    marker: PhantomData<Cx>,
}

impl<Cx> JSRoots<Cx> {
    pub fn new() -> JSRoots<Cx> {
        JSRoots {
            marker: PhantomData,
        }
    }
    pub fn root<'a, 'b, T>(&'a self, managed: JSManaged<'b, Cx, T>) -> JSManaged<'a, Cx, T::ChangeLifetime> where
        'a: 'b,
        T: JSManageable<'a>,
    {
        // The real thing would add the JS reflector to the root set
        JSManaged {
            raw: managed.raw as *mut T::ChangeLifetime,
            marker: PhantomData,
        }
    }
}

impl<Cx> Drop for JSRoots<Cx> {
    fn drop(&mut self) {
        // The real thing would unroot the root set.
    }
}

/// A snapshot of a JS context.
///
/// The idea here is that during the lifetime of a JSSnapshot<Cx>, the JS state
/// doesn't change, and in particular GC doesn't happen. This allows us to avoid
/// some rooting.
pub struct JSSnapshot<'c, Cx: 'c>(&'c mut Cx);

impl<'c, Cx: 'c> JSSnapshot<'c, Cx> where
    Cx: JSContext
{
    /// Build a new snapshot
    pub fn new(cx: &mut Cx) -> JSSnapshot<Cx> {
        JSSnapshot(cx)
    }

    /// Extend the lifetime of JS-managed data.
    /// This is safe because no GC will happen during the lifetime of this snapshot.
    pub fn extend_lifetime<'a, T>(&'a self, managed: JSManaged<'a, Cx, T>) -> JSManaged<'c, Cx, T::ChangeLifetime>
        where T: JSManageable<'c>
    {
        JSManaged {
            raw: managed.raw as *mut T::ChangeLifetime,
            marker: PhantomData,
        }
    }
}

impl<'c, Cx: 'c> JSAccess<Cx> for JSSnapshot<'c, Cx> where
    Cx: JSContext
{
    /// Read-only access to native JS-managed data.
    fn get<'a, 'b:'a, T>(&'a self, managed: JSManaged<'b, Cx, T>) -> &'a T::ChangeLifetime where
        T: JSManageable<'a>
    {
        self.0.get(managed)
    }

    /// Read-write access to native JS-managed data.
    fn get_mut<'a, 'b:'a, T>(&'a mut self, managed: JSManaged<'b, Cx, T>) -> &'a mut T::ChangeLifetime where
        T: JSManageable<'a>
    {
        self.0.get_mut(managed)
    }
}

// It is important for safety that this implemention is not made public!
struct JSContextImpl {
    // JS context implementation goes here
}

impl JSAccess<JSContextImpl> for JSContextImpl {
    // The claim is that this is safe, since it takes a `&self`.
    fn get<'a, 'b:'a, T>(&'a self, managed: JSManaged<'b, Self, T>) -> &'a T::ChangeLifetime where
        T: JSManageable<'a>
    {
        unsafe { &*(managed.raw as *mut T::ChangeLifetime) }
    }

    // The claim is that this is safe, since it takes a `&mut self`.
    fn get_mut<'a, 'b:'a, T>(&'a mut self, managed: JSManaged<'b, Self, T>) -> &'a mut T::ChangeLifetime where
        T: JSManageable<'a>
    {
        unsafe { &mut *(managed.raw as *mut T::ChangeLifetime) }
    }
}

impl JSContext for JSContextImpl {
    fn snapshot(&mut self) -> JSSnapshot<Self> {
        JSSnapshot(self)
    }

    // This outline implementation just space-leaks all data,
    // the real thing would create a reflector, and add a finalizer hook.
    fn manage<'a, T>(&'a self, value: T) -> JSManaged<'a, Self, T>
        where T: 'a + JSManageable<'a, ChangeLifetime=T>
    {
        JSManaged {
            raw: Box::into_raw(Box::new(value)),
            marker: PhantomData,
        }
    }
}

#[test]
// This test constructs a two-node cyclic graph, which is the smallest
// example of something that uses `RefCell`s in servo's JS bindings.
fn test() {
    // A graph type
    type Graph<'a, Cx> = JSManaged<'a, Cx, NativeGraph<'a, Cx>>;
    struct NativeGraph<'a, Cx> {
        nodes: Vec<Node<'a, Cx>>,
    }
    unsafe impl<'a, 'b, Cx: 'b> JSManageable<'b> for NativeGraph<'a, Cx> { type ChangeLifetime = NativeGraph<'b, Cx>; }
    unsafe impl<'a, Cx> JSTraceable<Cx> for NativeGraph<'a, Cx> {}
    // A node type
    type Node<'a, Cx> = JSManaged<'a, Cx, NativeNode<'a, Cx>>;
    struct NativeNode<'a, Cx> {
        data: usize,
        edges: Vec<Node<'a, Cx>>,
    }
    unsafe impl<'a, 'b, Cx: 'b> JSManageable<'b> for NativeNode<'a, Cx> { type ChangeLifetime = NativeNode<'b, Cx>; }
    unsafe impl<'a, Cx> JSTraceable<Cx> for NativeNode<'a, Cx> {}
    // Build a cyclic graph
    struct Test;
    impl JSContextConsumer<()> for Test {
        fn consume<Cx>(self, cx: &mut Cx) where Cx: JSContext {
            let roots = JSRoots::new();
            let graph = roots.root(cx.manage(NativeGraph { nodes: vec![] }));
            self.add_node(cx, graph, 1);
            self.add_node(cx, graph, 2);
            assert_eq!(graph.get(cx).nodes[0].get(cx).data, 1);
            assert_eq!(graph.get(cx).nodes[1].get(cx).data, 2);
            self.add_edge(&mut cx.snapshot(), graph, 0, 1);
            self.add_edge(&mut cx.snapshot(), graph, 1, 0);
            assert_eq!(graph.get(cx).nodes[0].get(cx).edges[0].get(cx).data, 2);
            assert_eq!(graph.get(cx).nodes[1].get(cx).edges[0].get(cx).data, 1);
        }
    }
    impl Test {
        fn add_node<Cx: JSContext>(&self, cx: &mut Cx, graph: Graph<Cx>, data: usize) {
            // Creating nodes does memory allocation, which may trigger GC,
            // so the node needs to be rooted while it is being added.
            let roots = JSRoots::new();
            let node1 = roots.root(cx.manage(NativeNode { data: data, edges: vec![] }));
            graph.get_mut(cx).nodes.push(node1);
        }
        fn add_edge<Cx: JSContext>(&self, cx: &mut JSSnapshot<Cx>, graph: Graph<Cx>, from: usize, to: usize) {
            // Note that there's no rooting here.
            let node1 = graph.get(cx).nodes[from].extend_lifetime(cx);
            let node2 = graph.get(cx).nodes[to].extend_lifetime(cx);
            node1.get_mut(cx).edges.push(node2);
        }
    }
    with_js_context(Test);
}

#[test]
fn test_covariant() {
    #[allow(dead_code)]
    fn cast<'a, 'b:'a, Cx, T>(managed: JSManaged<'b, Cx, T>) -> JSManaged<'a, Cx, T> {
        managed
    }
}
<commit_msg>Added changing the lifetime of JS-managed data.<commit_after>//! An outline of how linear types could be combined with JS-managed data
//!
//! The idea is to use the JS context as a linear token.
//! Each JS context gets its own type `Cx` which implements the `JSContext` trait.
//! Access to read-only JS-managed data requires a context of type `&Cx`.
//! Access to read-write JS-managed data requires a context of type `&mut Cx`.
//! Linear use of the context ensures that Rust's memory safety is preserved (er, I hope).
//!
//! This API doesn't address tracing, which would have to be handled similarly
//! to servo's current JS bindings.
//!
//! One thing that makes this easier is that we can arrange for any
//! calls into the JS engine which might trigger GC to take a `&mut Cx`
//! argument, which gives us control of when GC might occur.

use std::marker::PhantomData;

/// The trait for native JS-manageable data.
pub unsafe trait JSManageable<'a> {
    /// This type should have the same mnemory represention as `Self`.
    /// The only difference between `Self` and `Self::ChangeLifetime`
    /// is that any `JSManaged<'b, Cx, T>` should be replaced by
    /// `JSManaged<'a, Cx, T::ChangeLifetime>`.
    type ChangeLifetime: 'a;
}

/// The trait for accessing JS-managed data.
pub trait JSAccess<Cx>: Sized {
    /// Read-only access to native JS-managed data.
    fn get<'a, 'b:'a, T>(&'a self, managed: JSManaged<'b, Cx, T>) -> &'a T::ChangeLifetime where
        T: JSManageable<'a>;

    /// Read-write access to native JS-managed data.
    fn get_mut<'a, 'b:'a, T>(&'a mut self, managed: JSManaged<'b, Cx, T>) -> &'a mut T::ChangeLifetime where
        T: JSManageable<'a>;
}

/// The trait for JS contexts.
pub trait JSContext: JSAccess<Self> {
    /// Get a snapshot of the JS state.
    /// The snapshot only allows access to the methods that are guaranteed not to call GC,
    /// so we don't need to root JS-managed pointers during the lifetime of a snapshot.
    fn snapshot(&mut self) -> JSSnapshot<Self>;

    /// Give ownership of data to JS.
    /// This allocates JS heap, which may trigger GC.
    fn manage<'a, T>(&'a self, value: T) -> JSManaged<'a, Self, T>
        where T: 'a + JSManageable<'a, ChangeLifetime=T>;

    // A real implementation would also have JS methods such as those in jsapi.
}

/// A placholder for the real `JSTraceable`.
pub unsafe trait JSTraceable<Cx> {}

/// A user of a JS context implements `JSContextConsumer`, which is called back
/// with a fresh JS context.
pub trait JSContextConsumer<T> {
    /// This callback is called with a fresh JS context.
    fn consume<Cx>(self, cx: &mut Cx) -> T where Cx: JSContext;
}

/// To create a fresh JS context, the user implements `JSContextConsumer`
/// for their type `K`, builds a `k:K`, then calls `with_js_context(k)`.
/// ```rust
///   struct MyConsumer;
///   impl JSContextConsumer<()> for MyConsumer {
///      fn consume<Cx: JSContext>(cx: Cx) {
///         // Do stuff with the JS context cx.
///      }
///   }
///   with_js_context(MyConsumer);
/// ```
pub fn with_js_context<C, T>(consumer: C) -> T where
    C: JSContextConsumer<T>
{
    // A real implementation would allocate a JS context
    let mut cx = JSContextImpl {};
    consumer.consume(&mut cx)
}

/// The type of JS-managed data in a JS context `Cx`.
///
/// If the user has access to a `&JSManaged`, then the JS-managed
/// data is live for the lifetime of the reference. In particular,
/// this means that there should never be any stack-allocated
/// `JSManaged` values, since they would allow the user to construct
/// `&JSManaged` references with arbitrary lifetimes.
pub struct JSManaged<'a, Cx, T> {
    // JS reflector goes here
    raw: *mut T,
    marker: PhantomData<(&'a(),Cx)>,
}

impl<'a, Cx, T> Clone for JSManaged<'a, Cx, T> {
    fn clone(&self) -> Self {
        JSManaged {
            raw: self.raw,
            marker: self.marker,
        }
    }
}

impl<'a, Cx, T> Copy for JSManaged<'a, Cx, T> {
}

unsafe impl<'a, 'b, Cx, T> JSManageable<'b> for JSManaged<'a, Cx, T> where
    Cx: 'b,
    T: JSManageable<'b>,
{
    type ChangeLifetime = JSManaged<'b, Cx, T::ChangeLifetime>;
}

impl<'a, Cx, T> JSManaged<'a, Cx, T> {
    /// Convenience method for `access.get(self)`.
    pub fn get<'b, Access: JSAccess<Cx>>(self, access: &'b Access) -> &'b T::ChangeLifetime where
        T: JSManageable<'b>,
        'a: 'b,
    {
        access.get::<'b, 'b, T>(self)
    }

    /// Convenience method for `access.get_mut(self)`.
    pub fn get_mut<'b, Access: JSAccess<Cx>>(self, access: &'b mut Access) -> &'b mut T::ChangeLifetime where
        T: JSManageable<'b>,
        'a: 'b,
    {
        access.get_mut(self)
    }

    /// Change the lifetime of JS-managed data.
    pub unsafe fn change_lifetime<'b>(self) -> JSManaged<'b, Cx, T::ChangeLifetime> where
        T: JSManageable<'b>,
    {
        JSManaged {
            raw: self.raw as *mut T::ChangeLifetime,
            marker: PhantomData,
        }
    }

    /// It's safe to contract the lifetime of JS-managed data.
    pub fn contract_lifetime<'b>(self) -> JSManaged<'b, Cx, T::ChangeLifetime> where
        T: JSManageable<'b>,
        'a: 'b,
    {
        unsafe { self.change_lifetime() }
    }

    /// It's safe to extend the lifetime of JS-managed data if it has been snapshotted.
    pub fn extend_lifetime<'b>(self, _: &JSSnapshot<'b, Cx>) -> JSManaged<'b, Cx, T::ChangeLifetime> where
        T: JSManageable<'b>,
        'b: 'a,
    {
        unsafe { self.change_lifetime() }
    }
}

/// A root set.
pub struct JSRoots<Cx> {
    // The real thing would contain a set of rooted JS objects.
    marker: PhantomData<Cx>,
}

impl<Cx> JSRoots<Cx> {
    pub fn new() -> JSRoots<Cx> {
        JSRoots {
            marker: PhantomData,
        }
    }
    pub fn root<'a, 'b, T>(&'a self, managed: JSManaged<'b, Cx, T>) -> JSManaged<'a, Cx, T::ChangeLifetime> where
        'a: 'b,
        T: JSManageable<'a>,
    {
        // The real thing would add the JS reflector to the root set
        unsafe { managed.change_lifetime() }
    }
}

impl<Cx> Drop for JSRoots<Cx> {
    fn drop(&mut self) {
        // The real thing would unroot the root set.
    }
}

/// A snapshot of a JS context.
///
/// The idea here is that during the lifetime of a JSSnapshot<Cx>, the JS state
/// doesn't change, and in particular GC doesn't happen. This allows us to avoid
/// some rooting.
pub struct JSSnapshot<'c, Cx: 'c>(&'c mut Cx);

impl<'c, Cx: 'c> JSSnapshot<'c, Cx> where
    Cx: JSContext
{
    /// Build a new snapshot
    pub fn new(cx: &mut Cx) -> JSSnapshot<Cx> {
        JSSnapshot(cx)
    }
}

impl<'c, Cx: 'c> JSAccess<Cx> for JSSnapshot<'c, Cx> where
    Cx: JSContext
{
    /// Read-only access to native JS-managed data.
    fn get<'a, 'b:'a, T>(&'a self, managed: JSManaged<'b, Cx, T>) -> &'a T::ChangeLifetime where
        T: JSManageable<'a>
    {
        self.0.get(managed)
    }

    /// Read-write access to native JS-managed data.
    fn get_mut<'a, 'b:'a, T>(&'a mut self, managed: JSManaged<'b, Cx, T>) -> &'a mut T::ChangeLifetime where
        T: JSManageable<'a>
    {
        self.0.get_mut(managed)
    }
}

// It is important for safety that this implemention is not made public!
struct JSContextImpl {
    // JS context implementation goes here
}

impl JSAccess<JSContextImpl> for JSContextImpl {
    // The claim is that this is safe, since it takes a `&self`.
    fn get<'a, 'b:'a, T>(&'a self, managed: JSManaged<'b, Self, T>) -> &'a T::ChangeLifetime where
        T: JSManageable<'a>
    {
        unsafe { &*(managed.raw as *mut T::ChangeLifetime) }
    }

    // The claim is that this is safe, since it takes a `&mut self`.
    fn get_mut<'a, 'b:'a, T>(&'a mut self, managed: JSManaged<'b, Self, T>) -> &'a mut T::ChangeLifetime where
        T: JSManageable<'a>
    {
        unsafe { &mut *(managed.raw as *mut T::ChangeLifetime) }
    }
}

impl JSContext for JSContextImpl {
    fn snapshot(&mut self) -> JSSnapshot<Self> {
        JSSnapshot(self)
    }

    // This outline implementation just space-leaks all data,
    // the real thing would create a reflector, and add a finalizer hook.
    fn manage<'a, T>(&'a self, value: T) -> JSManaged<'a, Self, T>
        where T: 'a + JSManageable<'a, ChangeLifetime=T>
    {
        JSManaged {
            raw: Box::into_raw(Box::new(value)),
            marker: PhantomData,
        }
    }
}

#[test]
// This test constructs a two-node cyclic graph, which is the smallest
// example of something that uses `RefCell`s in servo's JS bindings.
fn test() {
    // A graph type
    type Graph<'a, Cx> = JSManaged<'a, Cx, NativeGraph<'a, Cx>>;
    struct NativeGraph<'a, Cx> {
        nodes: Vec<Node<'a, Cx>>,
    }
    unsafe impl<'a, 'b, Cx: 'b> JSManageable<'b> for NativeGraph<'a, Cx> { type ChangeLifetime = NativeGraph<'b, Cx>; }
    unsafe impl<'a, Cx> JSTraceable<Cx> for NativeGraph<'a, Cx> {}
    // A node type
    type Node<'a, Cx> = JSManaged<'a, Cx, NativeNode<'a, Cx>>;
    struct NativeNode<'a, Cx> {
        data: usize,
        edges: Vec<Node<'a, Cx>>,
    }
    unsafe impl<'a, 'b, Cx: 'b> JSManageable<'b> for NativeNode<'a, Cx> { type ChangeLifetime = NativeNode<'b, Cx>; }
    unsafe impl<'a, Cx> JSTraceable<Cx> for NativeNode<'a, Cx> {}
    // Build a cyclic graph
    struct Test;
    impl JSContextConsumer<()> for Test {
        fn consume<Cx>(self, cx: &mut Cx) where Cx: JSContext {
            let roots = JSRoots::new();
            let graph = roots.root(cx.manage(NativeGraph { nodes: vec![] }));
            self.add_nodes(cx, graph);
            assert_eq!(graph.get(cx).nodes[0].get(cx).data, 1);
            assert_eq!(graph.get(cx).nodes[1].get(cx).data, 2);
            self.add_edges(&mut cx.snapshot(), graph);
            assert_eq!(graph.get(cx).nodes[0].get(cx).edges[0].get(cx).data, 2);
            assert_eq!(graph.get(cx).nodes[1].get(cx).edges[0].get(cx).data, 1);
        }
    }
    impl Test {
        fn add_nodes<'a, 'b, Cx: JSContext>(&'a self, cx: &'a mut Cx, graph: Graph<'b, Cx>) {
            // Creating nodes does memory allocation, which may trigger GC,
            // so the nodes need to be rooted while they are being added.
            let roots = JSRoots::new();
            let node1 = roots.root(cx.manage(NativeNode { data: 1, edges: vec![] }));
            let node2 = roots.root(cx.manage(NativeNode { data: 2, edges: vec![] }));
            graph.get_mut(cx).nodes.push(node1.contract_lifetime());
            graph.get_mut(cx).nodes.push(node2.contract_lifetime());
        }
        fn add_edges<Cx: JSContext>(&self, cx: &mut JSSnapshot<Cx>, graph: Graph<Cx>) {
            // Note that there's no rooting here.
            let node1 = graph.get(cx).nodes[0].extend_lifetime(cx);
            let node2 = graph.get(cx).nodes[1].extend_lifetime(cx);
            node1.get_mut(cx).edges.push(node2.contract_lifetime());
            node2.get_mut(cx).edges.push(node1.contract_lifetime());
        }
    }
    #[allow(dead_code)]
    // Test that we can contract the lifetimes of nodes and graphs.
    fn contract_graph<'a, 'b:'a, Cx: 'b>(graph: Graph<'b, Cx>) -> Graph<'a, Cx> {
        graph.contract_lifetime()
    }
    with_js_context(Test);
}

#[test]
fn test_covariant() {
    #[allow(dead_code)]
    fn cast<'a, 'b:'a, Cx, T>(managed: JSManaged<'b, Cx, T>)
                              -> JSManaged<'a, Cx, T>
    {
        managed
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

extern crate chrono;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate oauthcli;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json as json;
extern crate url;

pub mod messages;

mod util;

pub use messages::StreamMessage;

use futures::{Async, Future, Poll, Stream};
use hyper::client::Client;
use hyper::status::StatusCode;
use util::{Lines, Timeout};
use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use std::io::{self, BufReader};
use std::time::{Duration, Instant};

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Token<'a>(pub &'a str, pub &'a str);

#[derive(Debug, Clone)]
pub struct TwitterUserStreamBuilder<'a> {
    consumer: Token<'a>,
    token: Token<'a>,
    client: Option<&'a Client>,
    end_point: Option<&'a str>,
    timeout: Duration,
    user_agent: Option<&'a str>,
}

pub struct TwitterUserStream {
    lines: Lines,
    timeout: Duration,
    timer: Timeout,
}

#[derive(Debug)]
pub enum Error {
    Url(url::ParseError),
    Hyper(hyper::Error),
    Http(StatusCode),
    Io(io::Error),
    TimedOut(u64),
}

pub type Result<T> = std::result::Result<T, Error>;

impl<'a> TwitterUserStreamBuilder<'a> {
    pub fn new(consumer: Token<'a>, token: Token<'a>) -> Self {
        TwitterUserStreamBuilder {
            consumer: consumer,
            token: token,
            client: None,
            end_point: None,
            timeout: Duration::from_secs(90),
            user_agent: None,
        }
    }

    pub fn client(&mut self, client: Option<&'a Client>) -> &mut Self {
        self.client = client;
        self
    }

    pub fn end_point(&mut self, url: Option<&'a str>) -> &mut Self {
        self.end_point = url;
        self
    }

    pub fn timeout(&mut self, timeout: Duration) -> &mut Self {
        self.timeout = timeout;
        self
    }

    pub fn user_agent(&mut self, user_agent: Option<&'a str>) -> &mut Self {
        self.user_agent = user_agent;
        self
    }

    pub fn login(&self) -> Result<TwitterUserStream> {
        use hyper::header::{Headers, Authorization, UserAgent};
        use hyper::status::StatusCode;
        use oauthcli::{OAuthAuthorizationHeaderBuilder, SignatureMethod};
        use url::Url;

        let end_point = self.end_point.unwrap_or("https://userstream.twitter.com/1.1/user.json?with=user");
        let url = Url::parse(end_point)?;

        let auth = OAuthAuthorizationHeaderBuilder::new(
            "GET", &url, self.consumer.0, self.consumer.1, SignatureMethod::HmacSha1)
            .token(self.token.0, self.token.1)
            .finish_for_twitter();

        let mut headers = Headers::new();
        headers.set(Authorization(auth));
        if let Some(ua) = self.user_agent {
            headers.set(UserAgent(ua.to_owned()));
        }

        let res = if let Some(client) = self.client {
            client
                .get(url)
                .headers(headers)
                .send()?
        } else {
            Client::new()
                .get(url)
                .headers(headers)
                .send()?
        };

        match &res.status {
            &StatusCode::Ok => (),
            _ => return Err(res.status.into()),
        }

        Ok(TwitterUserStream {
            lines: util::lines(BufReader::new(res)),
            timeout: self.timeout,
            timer: Timeout::after(self.timeout),
        })
    }
}

impl TwitterUserStream {
    pub fn login<'a>(consumer: Token<'a>, token: Token<'a>) -> Result<Self> {
        TwitterUserStreamBuilder::new(consumer, token).login()
    }
}

impl Stream for TwitterUserStream {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        use Async::*;

        trace!("TwitterUserStream::poll");

        loop {
            match self.lines.poll()? {
                Ready(line_opt) => {
                    match line_opt {
                        Some(line) => {
                            let now = Instant::now();
                            let mut timer = Timeout::after(self.timeout);
                            timer.park(now);
                            info!("duration since last message: {}", {
                                let elapsed = timer.when() - self.timer.when(); // = (now + timeout) - (last + timeout)
                                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000f64
                            });
                            self.timer = timer;

                            if line.is_empty() {
                                debug!("blank line");
                            } else {
                                return Ok(Ready(Some(line)));
                            }
                        },
                        None => return Ok(None.into()),
                    }
                },
                NotReady => {
                    if let Ok(Ready(())) = self.timer.poll() {
                        return Err(Error::TimedOut(self.timeout.as_secs()));
                    } else {
                        debug!("polled before being ready");
                        return Ok(NotReady);
                    }
                },
            }
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        use Error::*;

        match *self {
            Url(ref e) => e.description(),
            Hyper(ref e) => e.description(),
            Http(ref status) => status.canonical_reason().unwrap_or("<unknown status code>"),
            Io(ref e) => e.description(),
            TimedOut(_) => "timed out",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        use Error::*;

        match *self {
            Url(ref e) => Some(e),
            Hyper(ref e) => Some(e),
            Http(_) => None,
            Io(ref e) => Some(e),
            TimedOut(_) => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use Error::*;

        match *self {
            Url(ref e) => Display::fmt(e, f),
            Hyper(ref e) => Display::fmt(e, f),
            Http(ref code) => Display::fmt(code, f),
            Io(ref e) => Display::fmt(e, f),
            TimedOut(timeout) => write!(f, "connection timed out after {} sec", timeout),
        }
    }
}

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Url(e)
    }
}

impl From<hyper::Error> for Error {
    fn from(e: hyper::Error) -> Self {
        Error::Hyper(e)
    }
}

impl From<StatusCode> for Error {
    fn from(e: StatusCode) -> Self {
        Error::Http(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<commit_msg>Implement IntoIterator for TwitterUserStream<commit_after>#![feature(proc_macro)]

extern crate chrono;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;
extern crate oauthcli;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json as json;
extern crate url;

pub mod messages;

mod util;

pub use messages::StreamMessage;

use futures::{Async, Future, Poll, Stream};
use hyper::client::Client;
use hyper::status::StatusCode;
use util::{Lines, Timeout};
use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use std::io::{self, BufReader};
use std::time::{Duration, Instant};

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Token<'a>(pub &'a str, pub &'a str);

#[derive(Debug, Clone)]
pub struct TwitterUserStreamBuilder<'a> {
    consumer: Token<'a>,
    token: Token<'a>,
    client: Option<&'a Client>,
    end_point: Option<&'a str>,
    timeout: Duration,
    user_agent: Option<&'a str>,
}

pub struct TwitterUserStream {
    lines: Lines,
    timeout: Duration,
    timer: Timeout,
}

#[derive(Debug)]
pub enum Error {
    Url(url::ParseError),
    Hyper(hyper::Error),
    Http(StatusCode),
    Io(io::Error),
    TimedOut(u64),
}

pub type Result<T> = std::result::Result<T, Error>;

impl<'a> TwitterUserStreamBuilder<'a> {
    pub fn new(consumer: Token<'a>, token: Token<'a>) -> Self {
        TwitterUserStreamBuilder {
            consumer: consumer,
            token: token,
            client: None,
            end_point: None,
            timeout: Duration::from_secs(90),
            user_agent: None,
        }
    }

    pub fn client(&mut self, client: Option<&'a Client>) -> &mut Self {
        self.client = client;
        self
    }

    pub fn end_point(&mut self, url: Option<&'a str>) -> &mut Self {
        self.end_point = url;
        self
    }

    pub fn timeout(&mut self, timeout: Duration) -> &mut Self {
        self.timeout = timeout;
        self
    }

    pub fn user_agent(&mut self, user_agent: Option<&'a str>) -> &mut Self {
        self.user_agent = user_agent;
        self
    }

    pub fn login(&self) -> Result<TwitterUserStream> {
        use hyper::header::{Headers, Authorization, UserAgent};
        use hyper::status::StatusCode;
        use oauthcli::{OAuthAuthorizationHeaderBuilder, SignatureMethod};
        use url::Url;

        let end_point = self.end_point.unwrap_or("https://userstream.twitter.com/1.1/user.json?with=user");
        let url = Url::parse(end_point)?;

        let auth = OAuthAuthorizationHeaderBuilder::new(
            "GET", &url, self.consumer.0, self.consumer.1, SignatureMethod::HmacSha1)
            .token(self.token.0, self.token.1)
            .finish_for_twitter();

        let mut headers = Headers::new();
        headers.set(Authorization(auth));
        if let Some(ua) = self.user_agent {
            headers.set(UserAgent(ua.to_owned()));
        }

        let res = if let Some(client) = self.client {
            client
                .get(url)
                .headers(headers)
                .send()?
        } else {
            Client::new()
                .get(url)
                .headers(headers)
                .send()?
        };

        match &res.status {
            &StatusCode::Ok => (),
            _ => return Err(res.status.into()),
        }

        Ok(TwitterUserStream {
            lines: util::lines(BufReader::new(res)),
            timeout: self.timeout,
            timer: Timeout::after(self.timeout),
        })
    }
}

impl TwitterUserStream {
    pub fn login<'a>(consumer: Token<'a>, token: Token<'a>) -> Result<Self> {
        TwitterUserStreamBuilder::new(consumer, token).login()
    }
}

impl Stream for TwitterUserStream {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        use Async::*;

        trace!("TwitterUserStream::poll");

        loop {
            match self.lines.poll()? {
                Ready(line_opt) => {
                    match line_opt {
                        Some(line) => {
                            let now = Instant::now();
                            let mut timer = Timeout::after(self.timeout);
                            timer.park(now);
                            info!("duration since last message: {}", {
                                let elapsed = timer.when() - self.timer.when(); // = (now + timeout) - (last + timeout)
                                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000f64
                            });
                            self.timer = timer;

                            if line.is_empty() {
                                debug!("blank line");
                            } else {
                                return Ok(Ready(Some(line)));
                            }
                        },
                        None => return Ok(None.into()),
                    }
                },
                NotReady => {
                    if let Ok(Ready(())) = self.timer.poll() {
                        return Err(Error::TimedOut(self.timeout.as_secs()));
                    } else {
                        debug!("polled before being ready");
                        return Ok(NotReady);
                    }
                },
            }
        }
    }
}

impl IntoIterator for TwitterUserStream {
    type Item = Result<String>;
    type IntoIter = futures::stream::Wait<Self>;

    fn into_iter(self) -> Self::IntoIter {
        self.wait()
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        use Error::*;

        match *self {
            Url(ref e) => e.description(),
            Hyper(ref e) => e.description(),
            Http(ref status) => status.canonical_reason().unwrap_or("<unknown status code>"),
            Io(ref e) => e.description(),
            TimedOut(_) => "timed out",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        use Error::*;

        match *self {
            Url(ref e) => Some(e),
            Hyper(ref e) => Some(e),
            Http(_) => None,
            Io(ref e) => Some(e),
            TimedOut(_) => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use Error::*;

        match *self {
            Url(ref e) => Display::fmt(e, f),
            Hyper(ref e) => Display::fmt(e, f),
            Http(ref code) => Display::fmt(code, f),
            Io(ref e) => Display::fmt(e, f),
            TimedOut(timeout) => write!(f, "connection timed out after {} sec", timeout),
        }
    }
}

impl From<url::ParseError> for Error {
    fn from(e: url::ParseError) -> Self {
        Error::Url(e)
    }
}

impl From<hyper::Error> for Error {
    fn from(e: hyper::Error) -> Self {
        Error::Hyper(e)
    }
}

impl From<StatusCode> for Error {
    fn from(e: StatusCode) -> Self {
        Error::Http(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<|endoftext|>


<commit_before>use super::{backend, device, proxy::Proxy, runner, window};
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
use crate::event_loop::ControlFlow;
use crate::window::WindowId;
use std::clone::Clone;

pub struct WindowTarget<T: 'static> {
    pub(crate) runner: runner::Shared<T>,
}

impl<T> Clone for WindowTarget<T> {
    fn clone(&self) -> Self {
        WindowTarget {
            runner: self.runner.clone(),
        }
    }
}

impl<T> WindowTarget<T> {
    pub fn new() -> Self {
        WindowTarget {
            runner: runner::Shared::new(),
        }
    }

    pub fn proxy(&self) -> Proxy<T> {
        Proxy::new(self.runner.clone())
    }

    pub fn run(&self, event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>) {
        self.runner.set_listener(event_handler);
    }

    pub fn register(&self, canvas: &mut backend::Canvas) {
        let runner = self.runner.clone();
        canvas.on_blur(move || {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::Focused(false),
            });
        });

        let runner = self.runner.clone();
        canvas.on_focus(move || {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::Focused(true),
            });
        });

        let runner = self.runner.clone();
        canvas.on_keyboard_press(move |scancode, virtual_keycode, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::KeyboardInput {
                    device_id: DeviceId(unsafe { device::Id::dummy() }),
                    input: KeyboardInput {
                        scancode,
                        state: ElementState::Pressed,
                        virtual_keycode,
                        modifiers,
                    },
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_keyboard_release(move |scancode, virtual_keycode, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::KeyboardInput {
                    device_id: DeviceId(unsafe { device::Id::dummy() }),
                    input: KeyboardInput {
                        scancode,
                        state: ElementState::Released,
                        virtual_keycode,
                        modifiers,
                    },
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_received_character(move |char_code| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::ReceivedCharacter(char_code),
            });
        });

        let runner = self.runner.clone();
        canvas.on_cursor_leave(move |pointer_id| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::CursorLeft {
                    device_id: DeviceId(device::Id(pointer_id)),
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_cursor_enter(move |pointer_id| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::CursorEntered {
                    device_id: DeviceId(device::Id(pointer_id)),
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_cursor_move(move |pointer_id, position, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::CursorMoved {
                    device_id: DeviceId(device::Id(pointer_id)),
                    position,
                    modifiers,
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_mouse_press(move |pointer_id, button, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::MouseInput {
                    device_id: DeviceId(device::Id(pointer_id)),
                    state: ElementState::Released,
                    button,
                    modifiers,
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_mouse_release(move |pointer_id, button, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::MouseInput {
                    device_id: DeviceId(device::Id(pointer_id)),
                    state: ElementState::Pressed,
                    button,
                    modifiers,
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_mouse_wheel(move |pointer_id, delta, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::MouseWheel {
                    device_id: DeviceId(device::Id(pointer_id)),
                    delta,
                    phase: TouchPhase::Moved,
                    modifiers,
                },
            });
        });
    }
}
<commit_msg>Fix mouse release/press events<commit_after>use super::{backend, device, proxy::Proxy, runner, window};
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
use crate::event_loop::ControlFlow;
use crate::window::WindowId;
use std::clone::Clone;

pub struct WindowTarget<T: 'static> {
    pub(crate) runner: runner::Shared<T>,
}

impl<T> Clone for WindowTarget<T> {
    fn clone(&self) -> Self {
        WindowTarget {
            runner: self.runner.clone(),
        }
    }
}

impl<T> WindowTarget<T> {
    pub fn new() -> Self {
        WindowTarget {
            runner: runner::Shared::new(),
        }
    }

    pub fn proxy(&self) -> Proxy<T> {
        Proxy::new(self.runner.clone())
    }

    pub fn run(&self, event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>) {
        self.runner.set_listener(event_handler);
    }

    pub fn register(&self, canvas: &mut backend::Canvas) {
        let runner = self.runner.clone();
        canvas.on_blur(move || {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::Focused(false),
            });
        });

        let runner = self.runner.clone();
        canvas.on_focus(move || {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::Focused(true),
            });
        });

        let runner = self.runner.clone();
        canvas.on_keyboard_press(move |scancode, virtual_keycode, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::KeyboardInput {
                    device_id: DeviceId(unsafe { device::Id::dummy() }),
                    input: KeyboardInput {
                        scancode,
                        state: ElementState::Pressed,
                        virtual_keycode,
                        modifiers,
                    },
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_keyboard_release(move |scancode, virtual_keycode, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::KeyboardInput {
                    device_id: DeviceId(unsafe { device::Id::dummy() }),
                    input: KeyboardInput {
                        scancode,
                        state: ElementState::Released,
                        virtual_keycode,
                        modifiers,
                    },
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_received_character(move |char_code| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::ReceivedCharacter(char_code),
            });
        });

        let runner = self.runner.clone();
        canvas.on_cursor_leave(move |pointer_id| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::CursorLeft {
                    device_id: DeviceId(device::Id(pointer_id)),
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_cursor_enter(move |pointer_id| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::CursorEntered {
                    device_id: DeviceId(device::Id(pointer_id)),
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_cursor_move(move |pointer_id, position, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::CursorMoved {
                    device_id: DeviceId(device::Id(pointer_id)),
                    position,
                    modifiers,
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_mouse_press(move |pointer_id, button, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::MouseInput {
                    device_id: DeviceId(device::Id(pointer_id)),
                    state: ElementState::Pressed,
                    button,
                    modifiers,
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_mouse_release(move |pointer_id, button, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::MouseInput {
                    device_id: DeviceId(device::Id(pointer_id)),
                    state: ElementState::Released,
                    button,
                    modifiers,
                },
            });
        });

        let runner = self.runner.clone();
        canvas.on_mouse_wheel(move |pointer_id, delta, modifiers| {
            runner.send_event(Event::WindowEvent {
                window_id: WindowId(window::Id),
                event: WindowEvent::MouseWheel {
                    device_id: DeviceId(device::Id(pointer_id)),
                    delta,
                    phase: TouchPhase::Moved,
                    modifiers,
                },
            });
        });
    }
}
<|endoftext|>


<commit_before>pub mod boolean_index;

pub trait Index<TTerm> {
    type Query;
    type QueryResult;

    fn new() -> Self;

    fn index_document<TDocIterator: Iterator<Item=TTerm>>(&mut self, document: TDocIterator) -> usize;

    fn execute_query(&self, query: &Self::Query) -> Self::QueryResult;
}
<commit_msg>PersistentIndex Trait<commit_after>use std::io::Result;
use std::path::Path;

pub mod boolean_index;

pub trait Index<TTerm> {
    type Query;
    type QueryResult;

    fn new() -> Self;

    fn index_document<TDocIterator: Iterator<Item=TTerm>>(&mut self, document: TDocIterator) -> usize;

    fn execute_query(&self, query: &Self::Query) -> Self::QueryResult;
}

pub trait PersistentIndex {
    fn write_to_file(&self, path: &Path) -> Result<()>;

    fn read_from_file(path: &Path) -> Self;
}
<|endoftext|>