<commit_before>#![allow(dead_code)]
extern crate mio;
extern crate num;
extern crate log;
extern crate byteorder;

use std::sync::{Arc, RwLock};
use std::collections::BTreeMap;
use self::mio::{Token, Poll, Ready, PollOpt, Events};
use self::mio::tcp::{TcpListener, TcpStream};
use self::mio::channel::{channel, Sender, Receiver};
use network::tcp::{TcpConnection, TcpReaderCommand, TcpReader, TcpReaderCMD};
use event::*;
use std::thread;
use std::net::SocketAddr;
use std::str::FromStr;
use std::process;
use std::io::{Result, Error, ErrorKind};
use self::byteorder::{ByteOrder, BigEndian};
use self::num::BigInt;
use network::tcp::TOKEN_VALUE_SEP;

const TCP_SERVER_TOKEN: Token = Token(0);
const RECEIVER_CHANNEL_TOKEN: Token = Token(1);
const CURRENT_API_VERSION: u32 = 1;

pub enum TcpNetworkCMD {
    HandleClientConnection
}

pub struct TcpNetworkCommand {
    cmd: TcpNetworkCMD,
    conn: Vec<TcpConnection>
}

pub struct TcpNetwork {
    // token for current networking/node
    current_token: String,
    current_value: BigInt,
    current_value_square: BigInt,

    // base connections list
    pub connections: Arc<RwLock<BTreeMap<Token, TcpConnection>>>,
    // connections which are still not accepted
    pending_connections: BTreeMap<Token, TcpConnection>,

    sender_channel: Sender<TcpNetworkCommand>,
    receiver_channel: Receiver<TcpNetworkCommand>,
    // channel for triggering events from networking
    event_handler_channel: Sender<EventHandlerCommand>,
    // vector of channels for sending commands to TcpReaders
    reader_channels: Vec<Sender<TcpReaderCommand>>,
    // basic Round Rubin load balancer index for readers
    reader_channel_index: usize,

    // buffer for reading chunked data
    // making allocation once for performance
    data_buffer: Vec<u8>,

    // base poll object
    poll: Poll
}

impl TcpNetwork {
    pub fn new(current_token: String, current_value: String, event_channel: Sender<EventHandlerCommand>) -> TcpNetwork {
        let (s, r) = channel::<TcpNetworkCommand>();
        let cur_val = match BigInt::from_str(current_value.as_str()) {
            Ok(v) => v,
            Err(e) => {
                warn!("Unable to parse given prime value for current Node -> {}", e);
                process::exit(1);
            }
        };

        TcpNetwork {
            connections: Arc::new(RwLock::new(BTreeMap::new())),
            pending_connections: BTreeMap::new(),
            reader_channels: Vec::new(),
            event_handler_channel: event_channel,
            sender_channel: s,
            receiver_channel: r,
            reader_channel_index: 0,

            // allocation buffer with 5K bytes
            // we don't need more for TcpNetwork
            data_buffer: Vec::with_capacity(5000),

            // token for current networking/node
            current_token: current_token,
            current_value: cur_val.clone(),
            current_value_square: (cur_val.clone() * cur_val),
            poll: Poll::new().unwrap()
        }
    }

    pub fn channel(&self) -> Sender<TcpNetworkCommand> {
        self.sender_channel.clone()
    }

    fn get_reader(&mut self) -> &Sender<TcpReaderCommand> {
        if self.reader_channel_index >= self.reader_channels.len() {
            self.reader_channel_index = 0;
        }

        let r = &self.reader_channels[self.reader_channel_index];
        self.reader_channel_index += 1;
        return r;
    }

    // base function for running TcpNetwork service with TcpReaders
    pub fn run(&mut self, server_address: &str, readers_count: usize) {
        self.reader_channels.reserve(readers_count);
        for i in 0..readers_count {
            let mut r = TcpReader::new(self.connections.clone());
            self.reader_channels[i] = r.channel();
            thread::spawn(move || {
                r.run();
            });
        }

        // making TcpListener for making server socket
        let addr = match SocketAddr::from_str(server_address) {
            Ok(a) => a,
            Err(e) => {
                warn!("Unable to parse given server address {} -> {}", server_address, e);
                return;
            }
        };

        // binding TCP server
        let server_socket = match TcpListener::bind(&addr) {
            Ok(s) => s,
            Err(e) => {
                warn!("Unable to bind TCP Server to given address {} -> {}", server_address, e);
                return;
            }
        };

        match self.poll.register(&server_socket, TCP_SERVER_TOKEN, Ready::readable(), PollOpt::edge()) {
            Ok(_) => {},
            Err(e) => {
                warn!("Unable to register server socket to Poll service -> {}", e);
                return;
            }
        }

        match self.poll.register(&self.receiver_channel, RECEIVER_CHANNEL_TOKEN, Ready::readable(), PollOpt::edge()) {
            Ok(_) => {},
            Err(e) => {
                warn!("Unable to register receiver channel to Poll service -> {}", e);
                return;
            }
        }

        // making events for handling 5K events at once
        let mut events: Events = Events::with_capacity(5000);

        loop {
            let event_count = self.poll.poll(&mut events, None).unwrap();
            if event_count == 0 {
                continue;
            }

            for event in events.into_iter() {
                let token = event.token();
                if token == RECEIVER_CHANNEL_TOKEN {
                    // trying to get commands while there is available data
                    loop {
                        match self.receiver_channel.try_recv() {
                            Ok(cmd) => {
                                let mut c = cmd;
                                self.notify(&mut c);
                            }
                            // if we got error, then data is unavailable
                            // and breaking receive loop
                            Err(_) => break
                        }
                    }
                    continue;
                }

                let kind = event.kind();

                if kind == Ready::error() || kind == Ready::hup() {
                    if token == TCP_SERVER_TOKEN {
                        warn!("Got Error for TCP server, exiting Application");
                        process::exit(1);
                    }
                    // if this error on connection, then we need to close it
                    // self.close_connection(token, true);
                    continue;
                }

                if kind == Ready::readable() {
                    if token == TCP_SERVER_TOKEN {
                        self.acceptable(&server_socket);
                    } else {
                        self.readable(token);
                    }
                    continue;
                }

                if kind == Ready::writable() {
                    self.writable(token);
                    continue;
                }
            }

        }
    }

    pub fn connect(&mut self, address: &str) -> Result<()> {
        // making TcpListener for making server socket
        let addr = match SocketAddr::from_str(address) {
            Ok(a) => a,
            Err(_) => return Err(Error::new(ErrorKind::AddrNotAvailable, "Unable to make address lookup"))
        };

        // connecting to tcp client
        let socket = match TcpStream::connect(&addr) {
            Ok(s) => s,
            Err(e) => return Err(e)
        };

        // transfering connection by chanel for registering it
        // and making handshake
        let _ = self.sender_channel.send(TcpNetworkCommand {
            cmd: TcpNetworkCMD::HandleClientConnection,
            conn: vec![TcpConnection::new(socket)]
        });

        Ok(())
    }

    #[inline(always)]
    fn acceptable(&mut self, server_sock: &TcpListener) {
        loop {
            match server_sock.accept() {
                Ok((sock, _)) => {
                    let conn = TcpConnection::new(sock);
                    match self.poll.register(&conn.socket, conn.socket_token, Ready::readable(), PollOpt::edge()) {
                        Ok(_) => {
                            // inserting connection as a pending
                            self.pending_connections.insert(conn.socket_token, conn);
                        }

                        Err(e) => {
                            // after this accepted connection would be automatically deleted
                            // by closures deallocation
                            warn!("Unable to register accepted connection -> {}", e);
                        }
                    }
                }
                // if we got error on server accept process
                // we need to break accept loop and wait until new connections
                // would be available in event loop
                Err(_) => break
            }
        }
    }

    #[inline(always)]
    fn notify(&mut self, command: &mut TcpNetworkCommand) {
        match command.cmd {
            TcpNetworkCMD::HandleClientConnection => {
                let mut conn = match command.conn.pop() {
                    Some(c) => c,
                    None => return
                };

                // if we got here then we made successfull connection with server
                // now we need to write our API version
                let mut write_data = [0; 4];
                BigEndian::write_u32(&mut write_data, CURRENT_API_VERSION);
                let mut send_data = Vec::new();
                send_data.extend_from_slice(&write_data);
                conn.writae_queue.push(send_data);

                let token_value = (self.current_token.clone() + TOKEN_VALUE_SEP.to_string().as_str() + self.current_value.to_str_radix(10).as_str())
                                    .into_bytes();

                conn.writae_queue.push(token_value);
                match self.poll.register(&conn.socket, conn.socket_token, Ready::readable() | Ready::writable(), PollOpt::edge()) {
                    Ok(_) => {},
                    Err(e) => {
                        warn!("Unable to register client connection -> {}", e);
                        return;
                    }
                }

                // inserting connection for handling handshake information
                self.pending_connections.insert(conn.socket_token, conn);
            }
        }
    }

    #[inline(always)]
    fn readable(&mut self, token: Token) {
        // when we will return functuin without inserting back
        // this connection would be deallocated and would be automatically closed
        let mut conn =  match self.pending_connections.remove(&token) {
            Some(c) => c,
            None => return
        };

        // if we yet don't have an api version
        // reading it
        if conn.api_version <= 0 {
            match conn.read_api_version() {
                Ok(is_done) => {
                    // if we need more data for getting API version
                    // then wiating until socket would become readable again
                    if !is_done {
                        return;
                    }
                },
                Err(e) => {
                    // if we got WouldBlock, then this is Non Blocking socket
                    // and data still not available for this, so it's not a connection error
                    if e.kind() == ErrorKind::WouldBlock {
                        self.pending_connections.insert(token, conn);
                    }

                    return;
                }
            }
        }

        let (conn_token, conn_value, is_done) = match conn.read_token_value() {
            Ok((t,v,d)) => (t,v,d),
            Err(e) => {
                warn!("Error while reading connection token, closing connection -> {}", e);
                return;
            }
        };

        // if we got token and value
        // setting them up, and sending event to User level
        // for authenticating this connection
        if is_done {
            // deregistering connection from Networking loop, because we don't want to receive data anymore
            // until this connection is not accepted
            let _ = self.poll.deregister(&conn.socket);

            conn.token = conn_token;
            conn.value = match BigInt::from_str(conn_value.as_str()) {
                Ok(v) => v,
                Err(e) => {
                    warn!("Unable to convert value string, closing connection -> {}", e);
                    return;
                }
            };

            if conn.from_server {
                let _ = self.event_handler_channel.send(EventHandlerCommand {
                    cmd: EventHandlerCMD::TriggerFromEvent,
                    event: Arc::new(Event{
                        name: String::from(EVENT_ON_PENDING_CONNECTION),
                        from: conn.token.clone(),
                        target: String::new(),
                        data: conn_value,
                        path: String::new(),
                        public_data: String::new()
                    })
                });
            }
            else {
                // if this connection is from client, then we don't need to check it using User space code
                // just accepting connection after we have server node information
                self.accept_conn(conn.token.clone());
            }
        }

        // if we got here then all operations done
        // adding back connection for keeping it
        self.pending_connections.insert(token, conn);
    }

    #[inline(always)]
    fn writable(&mut self, token: Token) {
        // when we will return functuin without inserting back
        // this connection would be deallocated and would be automatically closed
        let mut conn =  match self.pending_connections.remove(&token) {
            Some(c) => c,
            None => return
        };

        let is_done = match conn.flush_write_queue() {
            Ok(d) => d,
            Err(e) => {
                warn!("Connection Write error, closing connection -> {}", e);
                return;
            }
        };

        // if we done with writing data
        // reregistering connection only readable again
        if is_done {
            match self.poll.reregister(&conn.socket, token, Ready::readable(), PollOpt::edge()) {
                Ok(_) => {},
                Err(e) => {
                    warn!("Unable to reregister connection as writable, closing connection -> {}", e);
                    return;
                }
            }
        }

        // if we got here then all operations done
        // adding back connection for keeping it
        self.pending_connections.insert(token, conn);
    }

    pub fn accept_conn(&mut self, token_str: String) {
        let mut t = Token(0);
        for (s_token, conn) in &self.pending_connections {
            // finding connection with given token
            if conn.token == token_str {
                t = *s_token;
                break;
            }
        }

        // deleting connection from pending connections list
        let c = match self.pending_connections.remove(&t) {
            Some(c) => c,
            // probably we wouldn't do this
            None => return
        };

        // clearing socket handle from Networking loop
        let _ = self.poll.deregister(&c.socket);

        // sending connection to TcpReader for registering it
        let _ = self.get_reader().send(TcpReaderCommand{
            cmd: TcpReaderCMD::HandleConnection,
            conn: vec![c]
        });
    }
}
<commit_msg>reoirdering functions<commit_after>#![allow(dead_code)]
extern crate mio;
extern crate num;
extern crate log;
extern crate byteorder;

use std::sync::{Arc, RwLock};
use std::collections::BTreeMap;
use self::mio::{Token, Poll, Ready, PollOpt, Events};
use self::mio::tcp::{TcpListener, TcpStream};
use self::mio::channel::{channel, Sender, Receiver};
use network::tcp::{TcpConnection, TcpReaderCommand, TcpReader, TcpReaderCMD};
use event::*;
use std::thread;
use std::net::SocketAddr;
use std::str::FromStr;
use std::process;
use std::io::{Result, Error, ErrorKind};
use self::byteorder::{ByteOrder, BigEndian};
use self::num::BigInt;
use network::tcp::TOKEN_VALUE_SEP;

const TCP_SERVER_TOKEN: Token = Token(0);
const RECEIVER_CHANNEL_TOKEN: Token = Token(1);
const CURRENT_API_VERSION: u32 = 1;

pub enum TcpNetworkCMD {
    HandleClientConnection
}

pub struct TcpNetworkCommand {
    cmd: TcpNetworkCMD,
    conn: Vec<TcpConnection>
}

pub struct TcpNetwork {
    // token for current networking/node
    current_token: String,
    current_value: BigInt,
    current_value_square: BigInt,

    // base connections list
    pub connections: Arc<RwLock<BTreeMap<Token, TcpConnection>>>,
    // connections which are still not accepted
    pending_connections: BTreeMap<Token, TcpConnection>,

    sender_channel: Sender<TcpNetworkCommand>,
    receiver_channel: Receiver<TcpNetworkCommand>,
    // channel for triggering events from networking
    event_handler_channel: Sender<EventHandlerCommand>,
    // vector of channels for sending commands to TcpReaders
    reader_channels: Vec<Sender<TcpReaderCommand>>,
    // basic Round Rubin load balancer index for readers
    reader_channel_index: usize,

    // buffer for reading chunked data
    // making allocation once for performance
    data_buffer: Vec<u8>,

    // base poll object
    poll: Poll
}

impl TcpNetwork {
    pub fn new(current_token: String, current_value: String, event_channel: Sender<EventHandlerCommand>) -> TcpNetwork {
        let (s, r) = channel::<TcpNetworkCommand>();
        let cur_val = match BigInt::from_str(current_value.as_str()) {
            Ok(v) => v,
            Err(e) => {
                warn!("Unable to parse given prime value for current Node -> {}", e);
                process::exit(1);
            }
        };

        TcpNetwork {
            connections: Arc::new(RwLock::new(BTreeMap::new())),
            pending_connections: BTreeMap::new(),
            reader_channels: Vec::new(),
            event_handler_channel: event_channel,
            sender_channel: s,
            receiver_channel: r,
            reader_channel_index: 0,

            // allocation buffer with 5K bytes
            // we don't need more for TcpNetwork
            data_buffer: Vec::with_capacity(5000),

            // token for current networking/node
            current_token: current_token,
            current_value: cur_val.clone(),
            current_value_square: (cur_val.clone() * cur_val),
            poll: Poll::new().unwrap()
        }
    }

    pub fn channel(&self) -> Sender<TcpNetworkCommand> {
        self.sender_channel.clone()
    }

    // base function for running TcpNetwork service with TcpReaders
    pub fn run(&mut self, server_address: &str, readers_count: usize) {
        self.reader_channels.reserve(readers_count);
        for i in 0..readers_count {
            let mut r = TcpReader::new(self.connections.clone());
            self.reader_channels[i] = r.channel();
            thread::spawn(move || {
                r.run();
            });
        }

        // making TcpListener for making server socket
        let addr = match SocketAddr::from_str(server_address) {
            Ok(a) => a,
            Err(e) => {
                warn!("Unable to parse given server address {} -> {}", server_address, e);
                return;
            }
        };

        // binding TCP server
        let server_socket = match TcpListener::bind(&addr) {
            Ok(s) => s,
            Err(e) => {
                warn!("Unable to bind TCP Server to given address {} -> {}", server_address, e);
                return;
            }
        };

        match self.poll.register(&server_socket, TCP_SERVER_TOKEN, Ready::readable(), PollOpt::edge()) {
            Ok(_) => {},
            Err(e) => {
                warn!("Unable to register server socket to Poll service -> {}", e);
                return;
            }
        }

        match self.poll.register(&self.receiver_channel, RECEIVER_CHANNEL_TOKEN, Ready::readable(), PollOpt::edge()) {
            Ok(_) => {},
            Err(e) => {
                warn!("Unable to register receiver channel to Poll service -> {}", e);
                return;
            }
        }

        // making events for handling 5K events at once
        let mut events: Events = Events::with_capacity(5000);

        loop {
            let event_count = self.poll.poll(&mut events, None).unwrap();
            if event_count == 0 {
                continue;
            }

            for event in events.into_iter() {
                let token = event.token();
                if token == RECEIVER_CHANNEL_TOKEN {
                    // trying to get commands while there is available data
                    loop {
                        match self.receiver_channel.try_recv() {
                            Ok(cmd) => {
                                let mut c = cmd;
                                self.notify(&mut c);
                            }
                            // if we got error, then data is unavailable
                            // and breaking receive loop
                            Err(_) => break
                        }
                    }
                    continue;
                }

                let kind = event.kind();

                if kind == Ready::error() || kind == Ready::hup() {
                    if token == TCP_SERVER_TOKEN {
                        warn!("Got Error for TCP server, exiting Application");
                        process::exit(1);
                    }
                    // if this error on connection, then we need to close it
                    // self.close_connection(token, true);
                    continue;
                }

                if kind == Ready::readable() {
                    if token == TCP_SERVER_TOKEN {
                        self.acceptable(&server_socket);
                    } else {
                        self.readable(token);
                    }
                    continue;
                }

                if kind == Ready::writable() {
                    self.writable(token);
                    continue;
                }
            }

        }
    }

    pub fn connect(&mut self, address: &str) -> Result<()> {
        // making TcpListener for making server socket
        let addr = match SocketAddr::from_str(address) {
            Ok(a) => a,
            Err(_) => return Err(Error::new(ErrorKind::AddrNotAvailable, "Unable to make address lookup"))
        };

        // connecting to tcp client
        let socket = match TcpStream::connect(&addr) {
            Ok(s) => s,
            Err(e) => return Err(e)
        };

        // transfering connection by chanel for registering it
        // and making handshake
        let _ = self.sender_channel.send(TcpNetworkCommand {
            cmd: TcpNetworkCMD::HandleClientConnection,
            conn: vec![TcpConnection::new(socket)]
        });

        Ok(())
    }

    pub fn accept_conn(&mut self, token_str: String) {
        let mut t = Token(0);
        for (s_token, conn) in &self.pending_connections {
            // finding connection with given token
            if conn.token == token_str {
                t = *s_token;
                break;
            }
        }

        // deleting connection from pending connections list
        let c = match self.pending_connections.remove(&t) {
            Some(c) => c,
            // probably we wouldn't do this
            None => return
        };

        // clearing socket handle from Networking loop
        let _ = self.poll.deregister(&c.socket);

        // sending connection to TcpReader for registering it
        let _ = self.get_reader().send(TcpReaderCommand{
            cmd: TcpReaderCMD::HandleConnection,
            conn: vec![c]
        });
    }

    #[inline(always)]
    fn acceptable(&mut self, server_sock: &TcpListener) {
        loop {
            match server_sock.accept() {
                Ok((sock, _)) => {
                    let conn = TcpConnection::new(sock);
                    match self.poll.register(&conn.socket, conn.socket_token, Ready::readable(), PollOpt::edge()) {
                        Ok(_) => {
                            // inserting connection as a pending
                            self.pending_connections.insert(conn.socket_token, conn);
                        }

                        Err(e) => {
                            // after this accepted connection would be automatically deleted
                            // by closures deallocation
                            warn!("Unable to register accepted connection -> {}", e);
                        }
                    }
                }
                // if we got error on server accept process
                // we need to break accept loop and wait until new connections
                // would be available in event loop
                Err(_) => break
            }
        }
    }

    #[inline(always)]
    fn notify(&mut self, command: &mut TcpNetworkCommand) {
        match command.cmd {
            TcpNetworkCMD::HandleClientConnection => {
                let mut conn = match command.conn.pop() {
                    Some(c) => c,
                    None => return
                };

                // if we got here then we made successfull connection with server
                // now we need to write our API version
                let mut write_data = [0; 4];
                BigEndian::write_u32(&mut write_data, CURRENT_API_VERSION);
                let mut send_data = Vec::new();
                send_data.extend_from_slice(&write_data);
                conn.writae_queue.push(send_data);

                let token_value = (self.current_token.clone() + TOKEN_VALUE_SEP.to_string().as_str() + self.current_value.to_str_radix(10).as_str())
                                    .into_bytes();

                conn.writae_queue.push(token_value);
                match self.poll.register(&conn.socket, conn.socket_token, Ready::readable() | Ready::writable(), PollOpt::edge()) {
                    Ok(_) => {},
                    Err(e) => {
                        warn!("Unable to register client connection -> {}", e);
                        return;
                    }
                }

                // inserting connection for handling handshake information
                self.pending_connections.insert(conn.socket_token, conn);
            }
        }
    }

    #[inline(always)]
    fn readable(&mut self, token: Token) {
        // when we will return functuin without inserting back
        // this connection would be deallocated and would be automatically closed
        let mut conn =  match self.pending_connections.remove(&token) {
            Some(c) => c,
            None => return
        };

        // if we yet don't have an api version
        // reading it
        if conn.api_version <= 0 {
            match conn.read_api_version() {
                Ok(is_done) => {
                    // if we need more data for getting API version
                    // then wiating until socket would become readable again
                    if !is_done {
                        return;
                    }
                },
                Err(e) => {
                    // if we got WouldBlock, then this is Non Blocking socket
                    // and data still not available for this, so it's not a connection error
                    if e.kind() == ErrorKind::WouldBlock {
                        self.pending_connections.insert(token, conn);
                    }

                    return;
                }
            }
        }

        let (conn_token, conn_value, is_done) = match conn.read_token_value() {
            Ok((t,v,d)) => (t,v,d),
            Err(e) => {
                warn!("Error while reading connection token, closing connection -> {}", e);
                return;
            }
        };

        // if we got token and value
        // setting them up, and sending event to User level
        // for authenticating this connection
        if is_done {
            // deregistering connection from Networking loop, because we don't want to receive data anymore
            // until this connection is not accepted
            let _ = self.poll.deregister(&conn.socket);

            conn.token = conn_token;
            conn.value = match BigInt::from_str(conn_value.as_str()) {
                Ok(v) => v,
                Err(e) => {
                    warn!("Unable to convert value string, closing connection -> {}", e);
                    return;
                }
            };

            if conn.from_server {
                let _ = self.event_handler_channel.send(EventHandlerCommand {
                    cmd: EventHandlerCMD::TriggerFromEvent,
                    event: Arc::new(Event{
                        name: String::from(EVENT_ON_PENDING_CONNECTION),
                        from: conn.token.clone(),
                        target: String::new(),
                        data: conn_value,
                        path: String::new(),
                        public_data: String::new()
                    })
                });
            }
            else {
                // if this connection is from client, then we don't need to check it using User space code
                // just accepting connection after we have server node information
                self.accept_conn(conn.token.clone());
            }
        }

        // if we got here then all operations done
        // adding back connection for keeping it
        self.pending_connections.insert(token, conn);
    }

    #[inline(always)]
    fn writable(&mut self, token: Token) {
        // when we will return functuin without inserting back
        // this connection would be deallocated and would be automatically closed
        let mut conn =  match self.pending_connections.remove(&token) {
            Some(c) => c,
            None => return
        };

        let is_done = match conn.flush_write_queue() {
            Ok(d) => d,
            Err(e) => {
                warn!("Connection Write error, closing connection -> {}", e);
                return;
            }
        };

        // if we done with writing data
        // reregistering connection only readable again
        if is_done {
            match self.poll.reregister(&conn.socket, token, Ready::readable(), PollOpt::edge()) {
                Ok(_) => {},
                Err(e) => {
                    warn!("Unable to reregister connection as writable, closing connection -> {}", e);
                    return;
                }
            }
        }

        // if we got here then all operations done
        // adding back connection for keeping it
        self.pending_connections.insert(token, conn);
    }

    fn get_reader(&mut self) -> &Sender<TcpReaderCommand> {
        if self.reader_channel_index >= self.reader_channels.len() {
            self.reader_channel_index = 0;
        }

        let r = &self.reader_channels[self.reader_channel_index];
        self.reader_channel_index += 1;
        return r;
    }
}
<|endoftext|>


<commit_before>use std::io;
use time;
use term::Terminal;
use term::color::Color;
use term::color;

static WARN_COLOR_NSEC:  u64 = 1  * NSEC_PER_SEC;
static ERROR_COLOR_NSEC: u64 = 10 * NSEC_PER_SEC;
static NSEC_PER_SEC:     u64 = 1000000000;

static COLOR_OK:   Color = color::GREEN;
static COLOR_NG:   Color = color::RED;
static COLOR_WARN: Color = color::YELLOW;

pub struct Problem<'a> {
    pub id: uint,
    pub answer: &'a str,
    pub solve: fn() -> ~str
}

impl<'a> Problem<'a> {
    pub fn solve(&self) -> Solution {
        let (time, answer) = bench(|| (self.solve)());
        Solution {
            name: self.id.to_str(),
            is_correct: answer.equiv(&self.answer),
            answer: answer,
            time: time
        }
    }
}

pub struct Solution {
    name: ~str,
    is_correct: bool,
    answer: ~str,
    time: u64
}

impl Solution {
    pub fn new(name: ~str, is_correct: bool, answer: ~str, time: u64) -> Solution {
        Solution {
            name: name,
            is_correct: is_correct,
            answer: answer,
            time: time
        }
    }

    #[inline] pub fn is_correct(&self) -> bool { self.is_correct }
    #[inline] pub fn time(&self) -> u64 { self.time }

    pub fn print(&self, enable_time_color: bool) {
        fn ok(s: ~str) -> (Option<Color>, ~str) { (Some(COLOR_OK), s) }
        fn ng(s: ~str) -> (Option<Color>, ~str) { (Some(COLOR_NG), s) }
        fn warn(s: ~str) -> (Option<Color>, ~str) { (Some(COLOR_WARN), s) }
        fn normal(s: ~str) -> (Option<Color>, ~str) { (None, s) }

        let result_mark = if self.is_correct { ok("OK".TO_OWNED()) } else { ng("NG".TO_OWNED()) };
        let time_str = format!(" {:13}", nanosec_to_str(self.time));
        let time_mark = if !enable_time_color || self.time < WARN_COLOR_NSEC {
            normal(time_str)
        } else if self.time < ERROR_COLOR_NSEC {
            warn(time_str)
        } else {
            ng(time_str)
        };

        print_items(&[
                normal("[".to_owned()), result_mark, normal("]".to_owned()),
                normal(format!(" {:5}", self.name)),
                time_mark,
                normal(format!(" {:20}", self.answer)),
                normal("\n".to_owned())
                ]);
    }
}

fn nanosec_to_str(nsec: u64) -> ~str {
    return format!("{}.{:09}",
         (nsec / NSEC_PER_SEC) as uint,
         (nsec % NSEC_PER_SEC) as uint);
}

fn bench<T>(f: || -> T) -> (u64, T) {
    let start_time = time::precise_time_ns();
    let result     = f();
    let end_time   = time::precise_time_ns();
    return (end_time - start_time, result);
}

fn print_items(items: &[(Option<Color>, ~str)]) {
    match Terminal::new(io::stdout()) {
        Err(_) => {
            let mut out = io::stdout();
            for &(_, ref s) in items.iter() { let _ = out.write_str(*s); }
        },
        Ok(mut t) => {
            for &(c, ref s) in items.iter() {
                match c {
                    Some(c) => { let _ = t.fg(c); let _ = t.write_str(*s); let _ = t.reset(); }
                    None    => { let _ = t.write_str(*s); }
                }
            }
        }
    }
}
<commit_msg>fix for compile<commit_after>use std::io;
use time;
use term::Terminal;
use term::color::Color;
use term::color;

static WARN_COLOR_NSEC:  u64 = 1  * NSEC_PER_SEC;
static ERROR_COLOR_NSEC: u64 = 10 * NSEC_PER_SEC;
static NSEC_PER_SEC:     u64 = 1000000000;

static COLOR_OK:   Color = color::GREEN;
static COLOR_NG:   Color = color::RED;
static COLOR_WARN: Color = color::YELLOW;

pub struct Problem<'a> {
    pub id: uint,
    pub answer: &'a str,
    pub solve: fn() -> ~str
}

impl<'a> Problem<'a> {
    pub fn solve(&self) -> Solution {
        let (time, answer) = bench(|| (self.solve)());
        Solution {
            name: self.id.to_str(),
            is_correct: answer.equiv(&self.answer),
            answer: answer,
            time: time
        }
    }
}

pub struct Solution {
    name: ~str,
    is_correct: bool,
    answer: ~str,
    time: u64
}

impl Solution {
    pub fn new(name: ~str, is_correct: bool, answer: ~str, time: u64) -> Solution {
        Solution {
            name: name,
            is_correct: is_correct,
            answer: answer,
            time: time
        }
    }

    #[inline] pub fn is_correct(&self) -> bool { self.is_correct }
    #[inline] pub fn time(&self) -> u64 { self.time }

    pub fn print(&self, enable_time_color: bool) {
        fn ok(s: ~str) -> (Option<Color>, ~str) { (Some(COLOR_OK), s) }
        fn ng(s: ~str) -> (Option<Color>, ~str) { (Some(COLOR_NG), s) }
        fn warn(s: ~str) -> (Option<Color>, ~str) { (Some(COLOR_WARN), s) }
        fn normal(s: ~str) -> (Option<Color>, ~str) { (None, s) }

        let result_mark = if self.is_correct { ok("OK".to_owned()) } else { ng("NG".to_owned()) };
        let time_str = format!(" {:13}", nanosec_to_str(self.time));
        let time_mark = if !enable_time_color || self.time < WARN_COLOR_NSEC {
            normal(time_str)
        } else if self.time < ERROR_COLOR_NSEC {
            warn(time_str)
        } else {
            ng(time_str)
        };

        print_items(&[
                normal("[".to_owned()), result_mark, normal("]".to_owned()),
                normal(format!(" {:5}", self.name)),
                time_mark,
                normal(format!(" {:20}", self.answer)),
                normal("\n".to_owned())
                ]);
    }
}

fn nanosec_to_str(nsec: u64) -> ~str {
    return format!("{}.{:09}",
         (nsec / NSEC_PER_SEC) as uint,
         (nsec % NSEC_PER_SEC) as uint);
}

fn bench<T>(f: || -> T) -> (u64, T) {
    let start_time = time::precise_time_ns();
    let result     = f();
    let end_time   = time::precise_time_ns();
    return (end_time - start_time, result);
}

fn print_items(items: &[(Option<Color>, ~str)]) {
    match Terminal::new(io::stdout()) {
        Err(_) => {
            let mut out = io::stdout();
            for &(_, ref s) in items.iter() { let _ = out.write_str(*s); }
        },
        Ok(mut t) => {
            for &(c, ref s) in items.iter() {
                match c {
                    Some(c) => { let _ = t.fg(c); let _ = t.write_str(*s); let _ = t.reset(); }
                    None    => { let _ = t.write_str(*s); }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::agents::{GetPublicJwks, IncrAndTestLimits};
use crate::bridges;
use crate::config::LimitInput;
use crate::crypto::SigningAlgorithm;
use crate::email_address::EmailAddress;
use crate::error::BrokerError;
use crate::validation::parse_redirect_uri;
use crate::web::{html_response, json_response, Context, HandlerResult, ReturnParams};
use crate::webfinger::{self, Relation};
use futures_util::future::{self, Either};
use http::Method;
use log::info;
use serde_json::{from_value, json, Value};
use std::collections::HashSet;
use std::time::Duration;

/// Request handler to return the OpenID Discovery document.
///
/// Most of this is hard-coded for now, although the URLs are constructed by
/// using the base URL as configured in the `public_url` configuration value.
pub async fn discovery(ctx: &mut Context) -> HandlerResult {
    let obj = json!({
        "issuer": ctx.app.public_url,
        "authorization_endpoint": format!("{}/auth", ctx.app.public_url),
        "jwks_uri": format!("{}/keys.json", ctx.app.public_url),
        "scopes_supported": vec!["openid", "email"],
        "claims_supported": vec!["iss", "aud", "exp", "iat", "email"],
        "response_types_supported": vec!["id_token"],
        "response_modes_supported": vec!["form_post", "fragment"],
        "grant_types_supported": vec!["implicit"],
        "subject_types_supported": vec!["public"],
        "id_token_signing_alg_values_supported": &ctx.app.signing_algs,
        // NOTE: This field is non-standard.
        "accepts_id_token_signing_alg_query_param": true,
    });
    Ok(json_response(&obj, Some(ctx.app.discovery_ttl)))
}

/// Request handler for the JSON Web Key Set document.
///
/// Respond with the JWK key set containing all of the configured keys.
///
/// Relying Parties will need to fetch this data to be able to verify identity
/// tokens issued by this daemon instance.
pub async fn key_set(ctx: &mut Context) -> HandlerResult {
    let obj = json!({
        "keys": ctx.app.key_manager.send(GetPublicJwks).await
    });
    Ok(json_response(&obj, Some(ctx.app.keys_ttl)))
}

/// Request handler for authentication requests from the RP.
///
/// Calls the `oidc::request()` function if the provided email address's
/// domain matches one of the configured famous providers. Otherwise, calls the
/// `email::request()` function to allow authentication through the email loop.
pub async fn auth(ctx: &mut Context) -> HandlerResult {
    let mut params = match ctx.method {
        Method::GET => ctx.query_params(),
        Method::POST => ctx.form_params(),
        _ => unreachable!(),
    };

    let original_params = params.clone();

    let redirect_uri = try_get_input_param!(params, "redirect_uri");
    let client_id = try_get_input_param!(params, "client_id");
    let response_mode = try_get_input_param!(params, "response_mode", "fragment".to_owned());
    let response_errors = try_get_input_param!(params, "response_errors", "true".to_owned());
    let state = try_get_input_param!(params, "state", "".to_owned());

    let redirect_uri = parse_redirect_uri(&redirect_uri, "redirect_uri")
        .map_err(|e| BrokerError::Input(format!("{}", e)))?;

    if client_id != redirect_uri.origin().ascii_serialization() {
        return Err(BrokerError::Input(
            "the client_id must be the origin of the redirect_uri".to_owned(),
        ));
    }

    // Parse response_mode by wrapping it a JSON Value.
    // This has minimal overhead, and saves us a separate implementation.
    let response_mode = from_value(Value::String(response_mode)).map_err(|_err| {
        BrokerError::Input("unsupported response_mode, must be fragment or form_post".to_owned())
    })?;

    // NOTE: This query parameter is non-standard.
    let response_errors = response_errors
        .parse::<bool>()
        .map_err(|_err| BrokerError::Input("response_errors must be true or false".to_owned()))?;

    // Per the OAuth2 spec, we may redirect to the RP once we have validated client_id and
    // redirect_uri. In our case, this means we make redirect_uri available to error handling.
    let redirect_uri_ = redirect_uri.clone();
    ctx.return_params = Some(ReturnParams {
        redirect_uri,
        response_mode,
        response_errors,
        state,
    });

    if let Some(ref whitelist) = ctx.app.allowed_origins {
        if !whitelist.contains(&client_id) {
            return Err(BrokerError::Input(
                "the origin is not whitelisted".to_owned(),
            ));
        }
    }

    let nonce = try_get_input_param!(params, "nonce");
    if try_get_input_param!(params, "response_type") != "id_token" {
        return Err(BrokerError::Input(
            "unsupported response_type, only id_token is supported".to_owned(),
        ));
    }

    let scope = try_get_input_param!(params, "scope");
    let mut scope_set: HashSet<&str> = scope.split(' ').collect();
    scope_set.remove("email");
    if !scope_set.remove("openid") || !scope_set.is_empty() {
        return Err(BrokerError::Input(
            "unsupported scope, must contain 'openid' and optionally 'email'".to_owned(),
        ));
    }

    // NOTE: This query parameter is non-standard.
    let signing_alg = try_get_input_param!(params, "id_token_signing_alg", "RS256".to_owned());
    let signing_alg = signing_alg
        .parse()
        .ok()
        .filter(|alg| ctx.app.signing_algs.contains(alg))
        .ok_or_else(|| {
            BrokerError::Input(format!(
                "unsupported id_token_signing_alg, must be one of: {}",
                SigningAlgorithm::format_list(&*ctx.app.signing_algs)
            ))
        })?;

    let login_hint = try_get_input_param!(params, "login_hint", "".to_string());
    if login_hint.is_empty() && !ctx.want_json() {
        let display_origin = redirect_uri_.origin().unicode_serialization();

        let catalog = ctx.catalog();
        let data = mustache::MapBuilder::new()
            .insert_str("display_origin", display_origin)
            .insert_str("title", catalog.gettext("Finish logging in to"))
            .insert_str(
                "explanation",
                catalog.gettext("Login with your email address."),
            )
            .insert_str(
                "use",
                catalog.gettext("Please specify the email you wish to use to login with"),
            )
            .insert_vec("params", |mut builder| {
                for param in &original_params {
                    builder = builder.push_map(|builder| {
                        let (name, value) = param;
                        builder.insert_str("name", name).insert_str("value", value)
                    });
                }
                builder
            })
            .build();

        return Ok(html_response(
            ctx.app.templates.login_hint.render_data(&data),
        ));
    }

    // Verify and normalize the email.
    let email_addr = login_hint.parse::<EmailAddress>().map_err(|err| {
        BrokerError::Input(format!("login_hint is not a valid email address: {}", err))
    })?;

    // Enforce rate limits.
    match ctx
        .app
        .store
        .send(IncrAndTestLimits {
            input: LimitInput {
                email_addr: email_addr.clone(),
                origin: client_id.clone(),
                ip: ctx.ip,
            },
        })
        .await
    {
        Ok(true) => {}
        Ok(false) => return Err(BrokerError::RateLimited),
        Err(e) => {
            return Err(BrokerError::Internal(format!(
                "could not test rate limit: {}",
                e
            )))
        }
    }

    // Create the session with common data, but do not yet save it.
    ctx.start_session(
        &client_id,
        &login_hint,
        &email_addr,
        &nonce,
        signing_alg,
        ctx.ip,
    )
    .await;

    // Discover the authentication endpoints based on the email domain.
    let discovery_future = async {
        let links = webfinger::query(&ctx.app, &email_addr).await?;

        // Try to authenticate with the first provider.
        // TODO: Queue discovery of links and process in order, with individual timeouts.
        let link = links.first().ok_or(BrokerError::ProviderCancelled)?;
        match link.rel {
            // Portier and Google providers share an implementation
            Relation::Portier | Relation::Google => {
                bridges::oidc::auth(ctx, &email_addr, link).await
            }
        }
    };

    // Apply a timeout to discovery.
    let sleep = tokio::time::sleep(Duration::from_secs(5));
    tokio::pin!(sleep);
    match future::select(sleep, Box::pin(discovery_future)).await {
        Either::Left((_, _f)) => {
            // Timeout causes fall back to email loop auth.
            info!("discovery timed out for {}", email_addr);

            // TODO: We used to (before async) continue discovery in the background, using shared
            // access to Context through RefCell. We could bring that back by decoupling auth
            // mechanisms from Context.
            //
            // (The original idea was also for auth mechanisms to have a 'commit' action, to
            // indicate a side-effect is about the happen. From this side, it'd effectively abort
            // the timeout and bubble all errors. An intermediate AuthContext could provide this.)
            /*
            tokio::spawn(async {
                if let Err(e) = f.await {
                    e.log();
                }
            });
            */
        }
        Either::Right((Ok(v), _)) => {
            // Discovery succeeded, simply return the response.
            return Ok(v);
        }
        Either::Right((Err(e @ BrokerError::Provider(_)), _))
        | Either::Right((Err(e @ BrokerError::ProviderCancelled), _)) => {
            // Provider errors cause fallback to email loop auth.
            e.log(None).await;
        }
        Either::Right((Err(e), _)) => {
            // Other errors during discovery are bubbled.
            return Err(e);
        }
    }

    // Fall back to email loop auth.
    bridges::email::auth(ctx, email_addr).await
}
<commit_msg>Remove a `Box::pin` from discovery<commit_after>use crate::agents::{GetPublicJwks, IncrAndTestLimits};
use crate::bridges;
use crate::config::LimitInput;
use crate::crypto::SigningAlgorithm;
use crate::email_address::EmailAddress;
use crate::error::BrokerError;
use crate::validation::parse_redirect_uri;
use crate::web::{html_response, json_response, Context, HandlerResult, ReturnParams};
use crate::webfinger::{self, Relation};
use http::Method;
use log::info;
use serde_json::{from_value, json, Value};
use std::collections::HashSet;
use std::time::Duration;

/// Request handler to return the OpenID Discovery document.
///
/// Most of this is hard-coded for now, although the URLs are constructed by
/// using the base URL as configured in the `public_url` configuration value.
pub async fn discovery(ctx: &mut Context) -> HandlerResult {
    let obj = json!({
        "issuer": ctx.app.public_url,
        "authorization_endpoint": format!("{}/auth", ctx.app.public_url),
        "jwks_uri": format!("{}/keys.json", ctx.app.public_url),
        "scopes_supported": vec!["openid", "email"],
        "claims_supported": vec!["iss", "aud", "exp", "iat", "email"],
        "response_types_supported": vec!["id_token"],
        "response_modes_supported": vec!["form_post", "fragment"],
        "grant_types_supported": vec!["implicit"],
        "subject_types_supported": vec!["public"],
        "id_token_signing_alg_values_supported": &ctx.app.signing_algs,
        // NOTE: This field is non-standard.
        "accepts_id_token_signing_alg_query_param": true,
    });
    Ok(json_response(&obj, Some(ctx.app.discovery_ttl)))
}

/// Request handler for the JSON Web Key Set document.
///
/// Respond with the JWK key set containing all of the configured keys.
///
/// Relying Parties will need to fetch this data to be able to verify identity
/// tokens issued by this daemon instance.
pub async fn key_set(ctx: &mut Context) -> HandlerResult {
    let obj = json!({
        "keys": ctx.app.key_manager.send(GetPublicJwks).await
    });
    Ok(json_response(&obj, Some(ctx.app.keys_ttl)))
}

/// Request handler for authentication requests from the RP.
///
/// Calls the `oidc::request()` function if the provided email address's
/// domain matches one of the configured famous providers. Otherwise, calls the
/// `email::request()` function to allow authentication through the email loop.
pub async fn auth(ctx: &mut Context) -> HandlerResult {
    let mut params = match ctx.method {
        Method::GET => ctx.query_params(),
        Method::POST => ctx.form_params(),
        _ => unreachable!(),
    };

    let original_params = params.clone();

    let redirect_uri = try_get_input_param!(params, "redirect_uri");
    let client_id = try_get_input_param!(params, "client_id");
    let response_mode = try_get_input_param!(params, "response_mode", "fragment".to_owned());
    let response_errors = try_get_input_param!(params, "response_errors", "true".to_owned());
    let state = try_get_input_param!(params, "state", "".to_owned());

    let redirect_uri = parse_redirect_uri(&redirect_uri, "redirect_uri")
        .map_err(|e| BrokerError::Input(format!("{}", e)))?;

    if client_id != redirect_uri.origin().ascii_serialization() {
        return Err(BrokerError::Input(
            "the client_id must be the origin of the redirect_uri".to_owned(),
        ));
    }

    // Parse response_mode by wrapping it a JSON Value.
    // This has minimal overhead, and saves us a separate implementation.
    let response_mode = from_value(Value::String(response_mode)).map_err(|_err| {
        BrokerError::Input("unsupported response_mode, must be fragment or form_post".to_owned())
    })?;

    // NOTE: This query parameter is non-standard.
    let response_errors = response_errors
        .parse::<bool>()
        .map_err(|_err| BrokerError::Input("response_errors must be true or false".to_owned()))?;

    // Per the OAuth2 spec, we may redirect to the RP once we have validated client_id and
    // redirect_uri. In our case, this means we make redirect_uri available to error handling.
    let redirect_uri_ = redirect_uri.clone();
    ctx.return_params = Some(ReturnParams {
        redirect_uri,
        response_mode,
        response_errors,
        state,
    });

    if let Some(ref whitelist) = ctx.app.allowed_origins {
        if !whitelist.contains(&client_id) {
            return Err(BrokerError::Input(
                "the origin is not whitelisted".to_owned(),
            ));
        }
    }

    let nonce = try_get_input_param!(params, "nonce");
    if try_get_input_param!(params, "response_type") != "id_token" {
        return Err(BrokerError::Input(
            "unsupported response_type, only id_token is supported".to_owned(),
        ));
    }

    let scope = try_get_input_param!(params, "scope");
    let mut scope_set: HashSet<&str> = scope.split(' ').collect();
    scope_set.remove("email");
    if !scope_set.remove("openid") || !scope_set.is_empty() {
        return Err(BrokerError::Input(
            "unsupported scope, must contain 'openid' and optionally 'email'".to_owned(),
        ));
    }

    // NOTE: This query parameter is non-standard.
    let signing_alg = try_get_input_param!(params, "id_token_signing_alg", "RS256".to_owned());
    let signing_alg = signing_alg
        .parse()
        .ok()
        .filter(|alg| ctx.app.signing_algs.contains(alg))
        .ok_or_else(|| {
            BrokerError::Input(format!(
                "unsupported id_token_signing_alg, must be one of: {}",
                SigningAlgorithm::format_list(&*ctx.app.signing_algs)
            ))
        })?;

    let login_hint = try_get_input_param!(params, "login_hint", "".to_string());
    if login_hint.is_empty() && !ctx.want_json() {
        let display_origin = redirect_uri_.origin().unicode_serialization();

        let catalog = ctx.catalog();
        let data = mustache::MapBuilder::new()
            .insert_str("display_origin", display_origin)
            .insert_str("title", catalog.gettext("Finish logging in to"))
            .insert_str(
                "explanation",
                catalog.gettext("Login with your email address."),
            )
            .insert_str(
                "use",
                catalog.gettext("Please specify the email you wish to use to login with"),
            )
            .insert_vec("params", |mut builder| {
                for param in &original_params {
                    builder = builder.push_map(|builder| {
                        let (name, value) = param;
                        builder.insert_str("name", name).insert_str("value", value)
                    });
                }
                builder
            })
            .build();

        return Ok(html_response(
            ctx.app.templates.login_hint.render_data(&data),
        ));
    }

    // Verify and normalize the email.
    let email_addr = login_hint.parse::<EmailAddress>().map_err(|err| {
        BrokerError::Input(format!("login_hint is not a valid email address: {}", err))
    })?;

    // Enforce rate limits.
    match ctx
        .app
        .store
        .send(IncrAndTestLimits {
            input: LimitInput {
                email_addr: email_addr.clone(),
                origin: client_id.clone(),
                ip: ctx.ip,
            },
        })
        .await
    {
        Ok(true) => {}
        Ok(false) => return Err(BrokerError::RateLimited),
        Err(e) => {
            return Err(BrokerError::Internal(format!(
                "could not test rate limit: {}",
                e
            )))
        }
    }

    // Create the session with common data, but do not yet save it.
    ctx.start_session(
        &client_id,
        &login_hint,
        &email_addr,
        &nonce,
        signing_alg,
        ctx.ip,
    )
    .await;

    // Discover the authentication endpoints based on the email domain.
    let discovery_future = async {
        let links = webfinger::query(&ctx.app, &email_addr).await?;

        // Try to authenticate with the first provider.
        // TODO: Queue discovery of links and process in order, with individual timeouts.
        let link = links.first().ok_or(BrokerError::ProviderCancelled)?;
        match link.rel {
            // Portier and Google providers share an implementation
            Relation::Portier | Relation::Google => {
                bridges::oidc::auth(ctx, &email_addr, link).await
            }
        }
    };

    // Apply a timeout to discovery.
    match tokio::time::timeout(Duration::from_secs(5), discovery_future).await {
        Err(_) => {
            // Timeout causes fall back to email loop auth.
            info!("discovery timed out for {}", email_addr);

            // TODO: We used to (before async) continue discovery in the background, using shared
            // access to Context through RefCell. We could bring that back by decoupling auth
            // mechanisms from Context.
            //
            // (The original idea was also for auth mechanisms to have a 'commit' action, to
            // indicate a side-effect is about the happen. From this side, it'd effectively abort
            // the timeout and bubble all errors. An intermediate AuthContext could provide this.)
            /*
            tokio::spawn(async {
                if let Err(e) = f.await {
                    e.log();
                }
            });
            */
        }
        Ok(Ok(v)) => {
            // Discovery succeeded, simply return the response.
            return Ok(v);
        }
        Ok(Err(e @ BrokerError::Provider(_))) | Ok(Err(e @ BrokerError::ProviderCancelled)) => {
            // Provider errors cause fallback to email loop auth.
            e.log(None).await;
        }
        Ok(Err(e)) => {
            // Other errors during discovery are bubbled.
            return Err(e);
        }
    }

    // Fall back to email loop auth.
    bridges::email::auth(ctx, email_addr).await
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::Mutex;
use rand;
use rand::Rng;

use Request;
use Response;
use input;

pub struct SessionsManager<T> where T: Clone {
    // TODO: eventually replace the key with `[u8; 64]` or something similar
    sessions: Mutex<HashMap<String, T>>,
    cookie_name: String,
    timeout_s: u64,
}

impl<T> SessionsManager<T> where T: Clone {
    /// Initializes the sessions manager.
    ///
    /// # Parameters
    ///
    /// - `cookie_name`: The name of the cookie to use. Usually `SID`.
    /// - `timeout_s`: The duration of the session, in seconds. Usually 3600.
    ///
    pub fn new<S>(cookie_name: S, timeout_s: u64) -> SessionsManager<T> where S: Into<String> {
        SessionsManager {
            sessions: Mutex::new(HashMap::new()),
            cookie_name: cookie_name.into(),
            timeout_s: timeout_s,
        }
    }

    /// Tries to load an existing session from the request, or creates one if there
    /// is no session yet.
    pub fn start(&self, request: &Request) -> Session<T> {
        let mut cookie = input::get_cookies(request).into_iter();
        let cookie = cookie.find(|&(ref k, _)| k == &self.cookie_name);
        let cookie = cookie.map(|(k, v)| v);

        if let Some(cookie) = cookie {
            Session {
                manager: self,
                key: cookie,
            }
        } else {
            Session {
                manager: self,
                key: generate_session_id(),
            }
        }
    }
}

/// Represents an entry in the sessions manager.
pub struct Session<'a, T> where T: Clone + 'a {
    manager: &'a SessionsManager<T>,
    key: String,
}

impl<'a, T> Session<'a, T> where T: Clone {
    /// Load the session infos from the manager. Returns `None` if there is no data yet.
    ///
    /// Note that calling `get` twice in a row can produce different results. That can happen
    /// if two requests are processed in parallel and access the same session.
    pub fn get(&self) -> Option<T> {
        let session = self.manager.sessions.lock().unwrap();
        session.get(&self.key).map(|d| d.clone())
    }

    /// Stores the session infos in the manager.
    pub fn set(&self, value: T) {
        let mut session = self.manager.sessions.lock().unwrap();
        session.insert(self.key.clone(), value);
    }

    /// Applies the session on the `Response`. If you don't do that, the session won't be
    /// maintained on further connections.
    pub fn apply(&self, mut response: Response) -> Response {
        // FIXME: correct interactions with existing headers
        let header_value = format!("{}={}; Max-Age={}", self.manager.cookie_name, self.key,
                                                        self.manager.timeout_s);
        response.headers.push(("Set-Cookie".to_owned(), header_value));
        response
    }
}

/// Generates a string suitable for a session ID.
///
/// The output string doesn't contain any punctuation or character such as quotes or brackets
/// that could need to be escaped.
pub fn generate_session_id() -> String {
    // 5e+114 possibilities is reasonable
    rand::OsRng::new().unwrap()     // TODO: <- how to handle that?
                      .gen_ascii_chars()
                      .filter(|&c| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
                                   (c >= '0' && c <= '9'))
                      .take(64).collect::<String>()
}
<commit_msg>Add clear() to Session<commit_after>use std::collections::HashMap;
use std::sync::Mutex;
use rand;
use rand::Rng;

use Request;
use Response;
use input;

pub struct SessionsManager<T> where T: Clone {
    // TODO: eventually replace the key with `[u8; 64]` or something similar
    sessions: Mutex<HashMap<String, T>>,
    cookie_name: String,
    timeout_s: u64,
}

impl<T> SessionsManager<T> where T: Clone {
    /// Initializes the sessions manager.
    ///
    /// # Parameters
    ///
    /// - `cookie_name`: The name of the cookie to use. Usually `SID`.
    /// - `timeout_s`: The duration of the session, in seconds. Usually 3600.
    ///
    pub fn new<S>(cookie_name: S, timeout_s: u64) -> SessionsManager<T> where S: Into<String> {
        SessionsManager {
            sessions: Mutex::new(HashMap::new()),
            cookie_name: cookie_name.into(),
            timeout_s: timeout_s,
        }
    }

    /// Tries to load an existing session from the request, or creates one if there
    /// is no session yet.
    pub fn start(&self, request: &Request) -> Session<T> {
        let mut cookie = input::get_cookies(request).into_iter();
        let cookie = cookie.find(|&(ref k, _)| k == &self.cookie_name);
        let cookie = cookie.map(|(k, v)| v);

        if let Some(cookie) = cookie {
            Session {
                manager: self,
                key: cookie,
            }
        } else {
            Session {
                manager: self,
                key: generate_session_id(),
            }
        }
    }
}

/// Represents an entry in the sessions manager.
pub struct Session<'a, T> where T: Clone + 'a {
    manager: &'a SessionsManager<T>,
    key: String,
}

impl<'a, T> Session<'a, T> where T: Clone {
    /// Load the session infos from the manager. Returns `None` if there is no data yet.
    ///
    /// Note that calling `get` twice in a row can produce different results. That can happen
    /// if two requests are processed in parallel and access the same session.
    pub fn get(&self) -> Option<T> {
        let session = self.manager.sessions.lock().unwrap();
        session.get(&self.key).map(|d| d.clone())
    }

    /// Stores the session infos in the manager.
    pub fn set(&self, value: T) {
        let mut session = self.manager.sessions.lock().unwrap();
        session.insert(self.key.clone(), value);
    }

    /// Removes the session infos from the manager.
    pub fn clear(&self) {
        let mut session = self.manager.sessions.lock().unwrap();
        session.remove(&self.key);
    }

    /// Applies the session on the `Response`. If you don't do that, the session won't be
    /// maintained on further connections.
    pub fn apply(&self, mut response: Response) -> Response {
        // FIXME: correct interactions with existing headers
        let header_value = format!("{}={}; Max-Age={}", self.manager.cookie_name, self.key,
                                                        self.manager.timeout_s);
        response.headers.push(("Set-Cookie".to_owned(), header_value));
        response
    }
}

/// Generates a string suitable for a session ID.
///
/// The output string doesn't contain any punctuation or character such as quotes or brackets
/// that could need to be escaped.
pub fn generate_session_id() -> String {
    // 5e+114 possibilities is reasonable
    rand::OsRng::new().unwrap()     // TODO: <- how to handle that?
                      .gen_ascii_chars()
                      .filter(|&c| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
                                   (c >= '0' && c <= '9'))
                      .take(64).collect::<String>()
}
<|endoftext|>


<commit_before>extern crate sdl;
extern crate libc;

use libc::uint8_t;
//use std::ptr::RawPtr;

pub struct IOImpl {
    //keyboard_state: *uint8_t,
    keyboard_state : Vec<(sdl::event::Key, bool)>,
    key_set: [char, ..16]
}

fn index(keyset:[char, ..16], key:char) -> Option<u8> {
    for i in range(0u, keyset.len()) {
        if keyset[i] == key {
            return Some(i as u8);
    }
    }

    None
}

impl IOImpl {

    pub fn new(key_set: [char, ..16]) -> IOImpl {
        let a = 0;
        IOImpl { keyboard_state: sdl::event::get_key_state(), //unsafe {sdl::event::ll::SDL_GetKeyState(&a)},
                  key_set: key_set,
                }
    }

    pub fn get_key(&mut self) -> u8 {
        'key_loop : loop {
            match sdl::event::wait_event() {
            sdl::event::KeyEvent(k , _, _, _) =>  {
                match index(self.key_set, ((k as u8) as char)) {
                    Some(index) => { return index;},
                    None => {}
                };
            },

            _ => {}
            }
        }

    }

    pub fn key_pressed(&mut self, key:char) -> bool {
            sdl::event::pump_events(); /* Update current keyboard state */
            let state = sdl::event::get_key_state();
            match *state.get(key as uint) {
                (_, val) => val
            }
            //unsafe {sdl::event::ll::SDL_PumpEvents(); /* Update keyboard state */
            //        return *(self.keyboard_state.offset((key as u8) as int)) != 0;
            //}
    }

}
<commit_msg>Removed unneded crates and added function to check if the specified key has been pressed given the keyboard state<commit_after>extern crate sdl;

pub struct IOImpl {
    key_set: [char, ..16]
}

fn index(keyset:[char, ..16], key:char) -> Option<u8> {
    for i in range(0u, keyset.len()) {
        if keyset[i] == key {
            return Some(i as u8);
    }
    }

    None
}

impl IOImpl {

    pub fn new(key_set: [char, ..16]) -> IOImpl {
        let a = 0;
        IOImpl {  key_set: key_set}
    }

    pub fn get_key(&mut self) -> u8 {
        'key_loop : loop {
            match sdl::event::wait_event() {
            sdl::event::KeyEvent(k , _, _, _) =>  {
                match index(self.key_set, ((k as u8) as char)) {
                    Some(index) => { return index;},
                    None => {}
                };
            },

            _ => {}
            }
        }

    }

    fn is_pressed(keyboard_state : Vec<(sdl::event::Key, bool)>,  key: char) -> bool {
        for i in keyboard_state.iter() {
            match *i {
                (k, state) if (k as u8) == (key as u8) => return state,
                 _ => {} };
            }
        false
    }

    pub fn key_pressed(&mut self, key:char) -> bool {
            sdl::event::pump_events(); /* Update current keyboard state */
            let state = sdl::event::get_key_state();
            IOImpl::is_pressed(state, key)
    }
}
<|endoftext|>


<commit_before>fn main() {
}
<commit_msg>add rust solution for LargeSum<commit_after>macro_rules! o_o {
    ( $( $x:expr ),* ) => {
        {
            let mut tmp_vec = Vec::new();
            $(
                tmp_vec.push($x);
            )*
            tmp_vec
        }
    };
}

fn main() {
    let mut matrix: Vec<Vec<u64>> = Vec::new();
    matrix.push(o_o![3710728753, 3902102798, 7979982208, 3759024651, 135740250]);
    matrix.push(o_o![4637693767, 7490009712, 6481248969, 7007805041, 7018260538]);
    matrix.push(o_o![7432498619, 9524741059, 4742333095, 1305812372, 6617309629]);
    matrix.push(o_o![9194221336, 3574161572, 5224305633, 181107240,  6154908250]);
    matrix.push(o_o![2306758820, 7539346171, 1719803104, 2104751377, 8063246676]);
    matrix.push(o_o![8926167069, 6623633820, 1363784183, 8368417873, 4361726757]);
    matrix.push(o_o![2811287981, 2849979408, 654819315, 9262169127, 5889832738]);
    matrix.push(o_o![4427422891, 7432520321, 9235894228, 7679648767, 272189318]);
    matrix.push(o_o![4745144573, 6001306439, 911672168, 5684458871, 1603153276]);
    matrix.push(o_o![7038648610, 5843025439, 9396198289, 1759366568, 6757934951]);
    matrix.push(o_o![6217645714, 1856560629, 5021572231, 9658675507, 9324193331]);
    matrix.push(o_o![6490635246, 2741904929, 1014324458, 1382266334, 7944758178]);
    matrix.push(o_o![9257586771, 8337217661, 9637515905, 7923972824, 5598838407]);
    matrix.push(o_o![5820356532, 5359399008, 4026335689, 4883018945, 8628227828]);
    matrix.push(o_o![8018119938, 4826282014, 2781941399, 4056758715, 1170094390]);
    matrix.push(o_o![3539866437, 2827112653, 8299872407, 8447305319, 104293586]);
    matrix.push(o_o![8651550600, 6295864861, 5320752733, 7195919142, 517255829]);
    matrix.push(o_o![7169388870, 7715466499, 1155934876, 353292171, 4970056938]);
    matrix.push(o_o![5437007057, 6826684624, 6214956500, 7647178729, 4438377604]);
    matrix.push(o_o![5328265410, 8756828443, 1911906346, 9403785521, 7779295145]);
    matrix.push(o_o![3612327252, 5000296071, 750825638, 1565671088, 5258350721]);
    matrix.push(o_o![4587657617, 2410976447, 3391106072, 1826523687, 7223636045]);
    matrix.push(o_o![1742370690, 5851860660, 4482076212, 981328786, 733969412]);
    matrix.push(o_o![8114266041, 8086830619, 3284608111, 9106155694, 512689692]);
    matrix.push(o_o![5193432545, 1728388641, 9180470492, 9321505864, 2563049483]);
    matrix.push(o_o![6246722164, 8435076201, 7279180399, 4469300473, 2956340691]);
    matrix.push(o_o![1573244438, 6908125794, 5140890577, 622942919, 7107928209]);
    matrix.push(o_o![5503768752, 5678773091, 8625407449, 6984450833, 393682126]);
    matrix.push(o_o![1833638482, 5330154686, 1961243487, 6768129753, 4375946515]);
    matrix.push(o_o![8038628759, 2878490201, 5216855548, 2871720121, 9257766954]);
    matrix.push(o_o![7818283375, 7993103614, 7403568564, 4909552709, 7864797581]);
    matrix.push(o_o![1672632010, 436897842, 5535399209, 3183744149, 7806860984]);
    matrix.push(o_o![4840309812, 9077791799, 882187953, 2736447567, 5590848030]);
    matrix.push(o_o![8708698755, 1392711854, 5170785441, 6185242432, 693150332]);
    matrix.push(o_o![5995940689, 5756536782, 1070749269, 6653767632, 6235447210]);
    matrix.push(o_o![6979395067, 9652694742, 5977097391, 6669376304, 2633987085]);
    matrix.push(o_o![4105268470, 8299085211, 3994273657, 3411618276, 315001271]);
    matrix.push(o_o![6537860736, 1501080857, 91499395, 1255702819, 8746004375]);
    matrix.push(o_o![3582903531, 7434717326, 9321235781, 5498262974, 2552737307]);
    matrix.push(o_o![9495375976, 5105305946, 9660676831, 5657437716, 7401875275]);
    matrix.push(o_o![8890280257, 1733229619, 1766687138, 1993181104, 8770190271]);
    matrix.push(o_o![2526768027, 6078003013, 6786809925, 2546340106, 1632866526]);
    matrix.push(o_o![3627021854, 497705585, 6299465806, 3623799314, 746255962]);
    matrix.push(o_o![2407448690, 8231174977, 7923654662, 5724692332, 2810917141]);
    matrix.push(o_o![9143028819, 7103288597, 8066697608, 9293863828, 5025333403]);
    matrix.push(o_o![3441306557, 8016127815, 9218150055, 6186883646, 8420090470]);
    matrix.push(o_o![2305308117, 2816430487, 6237919698, 4248725503, 6638784583]);
    matrix.push(o_o![1148769693, 2154902810, 4240201383, 3512446218, 1441773470]);
    matrix.push(o_o![6378329949, 636259666, 4985876182, 2122522551, 2486764533]);
    matrix.push(o_o![6772018697, 1698544312, 4195724099, 1395900895, 2310058822]);
    matrix.push(o_o![9554825530, 263520781, 5322967962, 4948164195, 3868218774]);
    matrix.push(o_o![7608532713, 2285723110, 4248034561, 2486769706, 4507995236]);
    matrix.push(o_o![3777424253, 5411291684, 2768655389, 2620502491, 326572967]);
    matrix.push(o_o![2370191327, 5725675285, 6532482582, 6546309220, 7058596522]);
    matrix.push(o_o![2979886027, 2258331913, 1263751473, 4199488953, 4765745501]);
    matrix.push(o_o![1849570145, 4879288984, 8568277260, 7771372140, 3798879715]);
    matrix.push(o_o![3829820378, 3031473527, 7215803481, 4451349137, 3226651381]);
    matrix.push(o_o![3482954382, 9199918180, 2789165224, 3102739225, 1122869539]);
    matrix.push(o_o![4095795306, 6405232632, 5380441000, 5965493915, 9879593635]);
    matrix.push(o_o![2974615218, 5502371307, 6422551211, 8369380358, 388584903]);
    matrix.push(o_o![4169811622, 2072977186, 1582366784, 2468915799, 3532961922]);
    matrix.push(o_o![6246795719, 4401269043, 8771072750, 4810239089, 5523597457]);
    matrix.push(o_o![2318970677, 2547915061, 5055049539, 2297953090, 1129967519]);
    matrix.push(o_o![8618808822, 5875314529, 5840992512, 382900940, 7770775672]);
    matrix.push(o_o![1130673970, 8304724483, 8165338735, 234084564, 7058077308]);
    matrix.push(o_o![8295917476, 7140363198, 81871290, 1187549131, 547126581]);
    matrix.push(o_o![9762333104, 4818386269, 5154563349, 2636657289, 7563400500]);
    matrix.push(o_o![4284628018, 3517070527, 8318394258, 8214552122, 7251250327]);
    matrix.push(o_o![5512160354, 6981200581, 7621652128, 2765275169, 1296897789]);
    matrix.push(o_o![3223819573, 4329339946, 4375019078, 3694576588, 3352399886]);
    matrix.push(o_o![7550616496, 5184775180, 7381688378, 6109152735, 7929701337]);
    matrix.push(o_o![6217784275, 2192623401, 9423996391, 6804498399, 3173312731]);
    matrix.push(o_o![3292418570, 7147349566, 9166746876, 3466091503, 5914677504]);
    matrix.push(o_o![9951867143, 235219628, 8948901024, 2332511691, 3619626622]);
    matrix.push(o_o![7326746080, 591547471, 8307983928, 6853520694, 6944540724]);
    matrix.push(o_o![7684182252, 4674417161, 5140364279, 8227334805, 5556214818]);
    matrix.push(o_o![9714261791, 342598647, 2045168939, 8942217982, 6088076852]);
    matrix.push(o_o![8778364618, 2799346313, 7677543078, 936333301, 8982642090]);
    matrix.push(o_o![1084880252, 1674670883, 2151201858, 8354322381, 2876952786]);
    matrix.push(o_o![7132961247, 4782464538, 6369930090, 4931036361, 9763878039]);
    matrix.push(o_o![6218407357, 2399794223, 4062353938, 833965132, 7408011116]);
    matrix.push(o_o![6662789198, 1488087797, 9418768761, 4423003098, 4490851411]);
    matrix.push(o_o![6066182629, 3682836764, 7447792391, 8033511098, 9069790714]);
    matrix.push(o_o![8578694408, 9552990653, 6404474255, 7608365997, 6645795096]);
    matrix.push(o_o![6602439640, 9905389607, 1201982199, 7604759949, 197230297]);
    matrix.push(o_o![6491398268, 32973156, 371200413, 7790378556, 6085089252]);
    matrix.push(o_o![1673093931, 9872750275, 4689069037, 753941304, 2652315011]);
    matrix.push(o_o![9480937724, 5048795150, 9541009216, 4586375471, 598436791]);
    matrix.push(o_o![7863916702, 1187492431, 9957006419, 1796977759, 9028300699]);
    matrix.push(o_o![1536871371, 1936614952, 8113058763, 8027841075, 4449733078]);
    matrix.push(o_o![4078992311, 5535562561, 1423224232, 5503368544, 2488917353]);
    matrix.push(o_o![4488991150, 1440648020, 3690680639, 6067232219, 3204149535]);
    matrix.push(o_o![4150312888, 339536053, 2993403680, 697771065, 566631954]);
    matrix.push(o_o![8123488067, 3210146739, 585685579, 3458140362, 7822703280]);
    matrix.push(o_o![8261657077, 3948327592, 2328459417, 652509451, 2325230608]);
    matrix.push(o_o![2291880205, 8777319719, 8394501808, 8807242966, 1980811197]);
    matrix.push(o_o![7715854250, 2016545090, 4132458097, 8688277894, 8721859617]);
    matrix.push(o_o![7210783843, 5069186155, 4356628840, 6225747369, 2284509516]);
    matrix.push(o_o![2084960398, 134001723, 9306716668, 2355524525, 2804609722]);
    matrix.push(o_o![5350353422, 6472524250, 8740540755, 9178978126, 4330331690]);

    let mut result: u64 = 0;
    let mut j = 4;
    loop {
        for i in 0..100 {
            result = result + matrix[i][j];
        }

        if j > 0 {
            result = result / 10000000000;
        } else {
            break;
        }

        j = j - 1;
    }

    println!("{}", result);
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate mimir;
extern crate osmpbfreader;

use ::admin_geofinder::AdminGeoFinder;
use ::boundaries::{build_boundary, make_centroid};
use std::collections::{BTreeSet, BTreeMap};
use super::utils::*;
use super::OsmPbfReader;

pub type PoiTypes = BTreeMap<String, BTreeSet<String>>;
pub type PoisVec = Vec<mimir::Poi>;

#[derive(Debug)]
struct PoiMatcher {
    poi_types: PoiTypes,
}

impl PoiMatcher {
    pub fn new(types: PoiTypes) -> PoiMatcher {
        PoiMatcher { poi_types: types }
    }

    pub fn is_poi(&self, obj: &osmpbfreader::OsmObj) -> bool {
        self.poi_types.iter().any(|(poi_tag, poi_types)| {
            obj.tags().get(poi_tag).map_or(false, |poi_type| poi_types.contains(poi_type))
        })
    }
}

pub fn default_amenity_types() -> BTreeSet<String> {
    ["university",
     "hospital",
     "post_office",
     "bicycle_rental",
     "bicycle_parking",
     "parking",
     "police",
     "townhall"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

pub fn default_leisure_types() -> BTreeSet<String> {
    ["garden", "park"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

fn parse_poi(osmobj: &osmpbfreader::OsmObj,
             obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
             admins_geofinder: &AdminGeoFinder,
             city_level: u32)
             -> Option<mimir::Poi> {
    let (id, coord) = match *osmobj {
        osmpbfreader::OsmObj::Node(ref node) => {
            (format_poi_id("node", node.id), mimir::Coord::new(node.lat, node.lon))
        }
        osmpbfreader::OsmObj::Way(ref way) => {
            (format_poi_id("way", way.id), get_way_coord(obj_map, way))
        }
        osmpbfreader::OsmObj::Relation(ref relation) => {
            (format_poi_id("relation", relation.id),
             make_centroid(&build_boundary(&relation, &obj_map)))
        }
    };

    let name = osmobj.tags().get("name").map_or("", |name| name);

    if coord.is_default() {
        info!("The poi {} is rejected, cause: without coordinates.", id);
        return None;
    }

    if name == "" {
        info!("The poi {} is rejected, cause: without name.", id);
        return None;
    }

    let adms = admins_geofinder.get(&coord);
    let zip_codes = match osmobj.tags().get("addr:postcode") {
        Some(val) if !val.is_empty() => vec![val.clone()],
        _ => get_zip_codes_from_admins(&adms),
    };
    Some(mimir::Poi {
        id: id,
        name: name.to_string(),
        label: format_label(&adms, city_level, name),
        coord: coord,
        zip_codes: zip_codes,
        administrative_regions: adms,
        weight: 1,
    })
}

fn format_poi_id(_type: &str, id: i64) -> String {
    format!("poi:osm:{}:{}", _type, id)
}

pub fn pois(pbf: &mut OsmPbfReader,
            poi_types: PoiTypes,
            admins_geofinder: &AdminGeoFinder,
            city_level: u32)
            -> PoisVec {
    let matcher = PoiMatcher::new(poi_types);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_poi(o)).unwrap();
    objects.iter()
    	.filter(|&(_, obj)| matcher.is_poi(&obj))
    	.filter_map(|(_, obj)| parse_poi(obj, &objects, admins_geofinder, city_level))
    	.collect()
}

pub fn compute_poi_weight(pois_vec: &mut PoisVec, city_level: u32) {
    for poi in pois_vec {
        for admin in &mut poi.administrative_regions {
            if admin.level == city_level {
                poi.weight = admin.weight.get();
                break;
            }
        }
    }
}
<commit_msg>fmt passed<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate mimir;
extern crate osmpbfreader;

use ::admin_geofinder::AdminGeoFinder;
use ::boundaries::{build_boundary, make_centroid};
use std::collections::{BTreeSet, BTreeMap};
use super::utils::*;
use super::OsmPbfReader;

pub type PoiTypes = BTreeMap<String, BTreeSet<String>>;
pub type PoisVec = Vec<mimir::Poi>;

#[derive(Debug)]
struct PoiMatcher {
    poi_types: PoiTypes,
}

impl PoiMatcher {
    pub fn new(types: PoiTypes) -> PoiMatcher {
        PoiMatcher { poi_types: types }
    }

    pub fn is_poi(&self, obj: &osmpbfreader::OsmObj) -> bool {
        self.poi_types.iter().any(|(poi_tag, poi_types)| {
            obj.tags().get(poi_tag).map_or(false, |poi_type| poi_types.contains(poi_type))
        })
    }
}

pub fn default_amenity_types() -> BTreeSet<String> {
    ["university",
     "hospital",
     "post_office",
     "bicycle_rental",
     "bicycle_parking",
     "parking",
     "police",
     "townhall"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

pub fn default_leisure_types() -> BTreeSet<String> {
    ["garden", "park"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

fn parse_poi(osmobj: &osmpbfreader::OsmObj,
             obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
             admins_geofinder: &AdminGeoFinder,
             city_level: u32)
             -> Option<mimir::Poi> {
    let (id, coord) = match *osmobj {
        osmpbfreader::OsmObj::Node(ref node) => {
            (format_poi_id("node", node.id), mimir::Coord::new(node.lat, node.lon))
        }
        osmpbfreader::OsmObj::Way(ref way) => {
            (format_poi_id("way", way.id), get_way_coord(obj_map, way))
        }
        osmpbfreader::OsmObj::Relation(ref relation) => {
            (format_poi_id("relation", relation.id),
             make_centroid(&build_boundary(&relation, &obj_map)))
        }
    };

    let name = osmobj.tags().get("name").map_or("", |name| name);

    if coord.is_default() {
        info!("The poi {} is rejected, cause: without coordinates.", id);
        return None;
    }

    if name == "" {
        info!("The poi {} is rejected, cause: without name.", id);
        return None;
    }

    let adms = admins_geofinder.get(&coord);
    let zip_codes = match osmobj.tags().get("addr:postcode") {
        Some(val) if !val.is_empty() => vec![val.clone()],
        _ => get_zip_codes_from_admins(&adms),
    };
    Some(mimir::Poi {
        id: id,
        name: name.to_string(),
        label: format_label(&adms, city_level, name),
        coord: coord,
        zip_codes: zip_codes,
        administrative_regions: adms,
        weight: 1,
    })
}

fn format_poi_id(_type: &str, id: i64) -> String {
    format!("poi:osm:{}:{}", _type, id)
}

pub fn pois(pbf: &mut OsmPbfReader,
            poi_types: PoiTypes,
            admins_geofinder: &AdminGeoFinder,
            city_level: u32)
            -> PoisVec {
    let matcher = PoiMatcher::new(poi_types);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_poi(o)).unwrap();
    objects.iter()
        .filter(|&(_, obj)| matcher.is_poi(&obj))
        .filter_map(|(_, obj)| parse_poi(obj, &objects, admins_geofinder, city_level))
        .collect()
}

pub fn compute_poi_weight(pois_vec: &mut PoisVec, city_level: u32) {
    for poi in pois_vec {
        for admin in &mut poi.administrative_regions {
            if admin.level == city_level {
                poi.weight = admin.weight.get();
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>use ansi_term::Style;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Purple, Fixed};

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Colours {
    pub scale: bool,

    pub filetypes:  FileTypes,
    pub perms:      Permissions,
    pub size:       Size,
    pub users:      Users,
    pub links:      Links,
    pub git:        Git,

    pub punctuation:  Style,
    pub date:         Style,
    pub inode:        Style,
    pub blocks:       Style,
    pub header:       Style,

    pub symlink_path:     Style,
    pub broken_arrow:     Style,
    pub broken_filename:  Style,
    pub control_char:     Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct FileTypes {
    pub normal: Style,
    pub directory: Style,
    pub symlink: Style,
    pub pipe: Style,
    pub device: Style,
    pub socket: Style,
    pub special: Style,
    pub executable: Style,
    pub image: Style,
    pub video: Style,
    pub music: Style,
    pub lossless: Style,
    pub crypto: Style,
    pub document: Style,
    pub compressed: Style,
    pub temp: Style,
    pub immediate: Style,
    pub compiled: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Permissions {
    pub user_read:          Style,
    pub user_write:         Style,
    pub user_execute_file:  Style,
    pub user_execute_other: Style,

    pub group_read:    Style,
    pub group_write:   Style,
    pub group_execute: Style,

    pub other_read:    Style,
    pub other_write:   Style,
    pub other_execute: Style,

    pub attribute:  Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Size {
    pub numbers: Style,
    pub unit: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Users {
    pub user_you: Style,
    pub user_someone_else: Style,
    pub group_yours: Style,
    pub group_not_yours: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Links {
    pub normal: Style,
    pub multi_link_file: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Git {
    pub new: Style,
    pub modified: Style,
    pub deleted: Style,
    pub renamed: Style,
    pub typechange: Style,
}

impl Colours {
    pub fn plain() -> Colours {
        Colours::default()
    }

    pub fn colourful(scale: bool) -> Colours {
        Colours {
            scale: scale,

            filetypes: FileTypes {
                normal:      Style::default(),
                directory:   Blue.bold(),
                symlink:     Cyan.normal(),
                pipe:        Yellow.normal(),
                device:      Yellow.bold(),
                socket:      Red.bold(),
                special:     Yellow.normal(),
                executable:  Green.bold(),
                image:       Fixed(133).normal(),
                video:       Fixed(135).normal(),
                music:       Fixed(92).normal(),
                lossless:    Fixed(93).normal(),
                crypto:      Fixed(109).normal(),
                document:    Fixed(105).normal(),
                compressed:  Red.normal(),
                temp:        Fixed(244).normal(),
                immediate:   Yellow.bold().underline(),
                compiled:    Fixed(137).normal(),
            },

            perms: Permissions {
                user_read:           Yellow.bold(),
                user_write:          Red.bold(),
                user_execute_file:   Green.bold().underline(),
                user_execute_other:  Green.bold(),
                group_read:          Yellow.normal(),
                group_write:         Red.normal(),
                group_execute:       Green.normal(),
                other_read:          Yellow.normal(),
                other_write:         Red.normal(),
                other_execute:       Green.normal(),
                attribute:           Style::default(),
            },

            size: Size {
                numbers:  Green.bold(),
                unit:     Green.normal(),
            },

            users: Users {
                user_you:           Yellow.bold(),
                user_someone_else:  Style::default(),
                group_yours:        Yellow.bold(),
                group_not_yours:    Style::default(),
            },

            links: Links {
                normal:          Red.bold(),
                multi_link_file: Red.on(Yellow),
            },

            git: Git {
                new:         Green.normal(),
                modified:    Blue.normal(),
                deleted:     Red.normal(),
                renamed:     Yellow.normal(),
                typechange:  Purple.normal(),
            },

            punctuation:  Fixed(244).normal(),
            date:         Blue.normal(),
            inode:        Purple.normal(),
            blocks:       Cyan.normal(),
            header:       Style::default().underline(),

            symlink_path:     Cyan.normal(),
            broken_arrow:     Red.normal(),
            broken_filename:  Red.underline(),
            control_char:     Red.normal(),
        }
    }

    pub fn file_size(&self, size: u64) -> Style {
        if self.scale {
            if size < 1024 {
                Fixed(118).normal()
            }
            else if size < 1024 * 1024 {
                Fixed(190).normal()
            }
            else if size < 1024 * 1024 * 1024 {
                Fixed(226).normal()
            }
            else if size < 1024 * 1024 * 1024 * 1024 {
                Fixed(220).normal()
            }
            else {
                Fixed(214).normal()
            }
        }
        else {
            self.size.numbers
        }
    }
}
<commit_msg>Move scale colours to the Colours struct<commit_after>use ansi_term::Style;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Purple, Fixed};

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Colours {
    pub scale: bool,

    pub filetypes:  FileTypes,
    pub perms:      Permissions,
    pub size:       Size,
    pub users:      Users,
    pub links:      Links,
    pub git:        Git,

    pub punctuation:  Style,
    pub date:         Style,
    pub inode:        Style,
    pub blocks:       Style,
    pub header:       Style,

    pub symlink_path:     Style,
    pub broken_arrow:     Style,
    pub broken_filename:  Style,
    pub control_char:     Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct FileTypes {
    pub normal: Style,
    pub directory: Style,
    pub symlink: Style,
    pub pipe: Style,
    pub device: Style,
    pub socket: Style,
    pub special: Style,
    pub executable: Style,
    pub image: Style,
    pub video: Style,
    pub music: Style,
    pub lossless: Style,
    pub crypto: Style,
    pub document: Style,
    pub compressed: Style,
    pub temp: Style,
    pub immediate: Style,
    pub compiled: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Permissions {
    pub user_read:          Style,
    pub user_write:         Style,
    pub user_execute_file:  Style,
    pub user_execute_other: Style,

    pub group_read:    Style,
    pub group_write:   Style,
    pub group_execute: Style,

    pub other_read:    Style,
    pub other_write:   Style,
    pub other_execute: Style,

    pub attribute:  Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Size {
    pub numbers: Style,
    pub unit: Style,

    pub scale_byte: Style,
    pub scale_kilo: Style,
    pub scale_mega: Style,
    pub scale_giga: Style,
    pub scale_huge: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Users {
    pub user_you: Style,
    pub user_someone_else: Style,
    pub group_yours: Style,
    pub group_not_yours: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Links {
    pub normal: Style,
    pub multi_link_file: Style,
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Git {
    pub new: Style,
    pub modified: Style,
    pub deleted: Style,
    pub renamed: Style,
    pub typechange: Style,
}

impl Colours {
    pub fn plain() -> Colours {
        Colours::default()
    }

    pub fn colourful(scale: bool) -> Colours {
        Colours {
            scale: scale,

            filetypes: FileTypes {
                normal:      Style::default(),
                directory:   Blue.bold(),
                symlink:     Cyan.normal(),
                pipe:        Yellow.normal(),
                device:      Yellow.bold(),
                socket:      Red.bold(),
                special:     Yellow.normal(),
                executable:  Green.bold(),
                image:       Fixed(133).normal(),
                video:       Fixed(135).normal(),
                music:       Fixed(92).normal(),
                lossless:    Fixed(93).normal(),
                crypto:      Fixed(109).normal(),
                document:    Fixed(105).normal(),
                compressed:  Red.normal(),
                temp:        Fixed(244).normal(),
                immediate:   Yellow.bold().underline(),
                compiled:    Fixed(137).normal(),
            },

            perms: Permissions {
                user_read:           Yellow.bold(),
                user_write:          Red.bold(),
                user_execute_file:   Green.bold().underline(),
                user_execute_other:  Green.bold(),
                group_read:          Yellow.normal(),
                group_write:         Red.normal(),
                group_execute:       Green.normal(),
                other_read:          Yellow.normal(),
                other_write:         Red.normal(),
                other_execute:       Green.normal(),
                attribute:           Style::default(),
            },

            size: Size {
                numbers:  Green.bold(),
                unit:     Green.normal(),

                scale_byte: Fixed(118).normal(),
                scale_kilo: Fixed(190).normal(),
                scale_mega: Fixed(226).normal(),
                scale_giga: Fixed(220).normal(),
                scale_huge: Fixed(214).normal(),
            },

            users: Users {
                user_you:           Yellow.bold(),
                user_someone_else:  Style::default(),
                group_yours:        Yellow.bold(),
                group_not_yours:    Style::default(),
            },

            links: Links {
                normal:          Red.bold(),
                multi_link_file: Red.on(Yellow),
            },

            git: Git {
                new:         Green.normal(),
                modified:    Blue.normal(),
                deleted:     Red.normal(),
                renamed:     Yellow.normal(),
                typechange:  Purple.normal(),
            },

            punctuation:  Fixed(244).normal(),
            date:         Blue.normal(),
            inode:        Purple.normal(),
            blocks:       Cyan.normal(),
            header:       Style::default().underline(),

            symlink_path:     Cyan.normal(),
            broken_arrow:     Red.normal(),
            broken_filename:  Red.underline(),
            control_char:     Red.normal(),
        }
    }

    pub fn file_size(&self, size: u64) -> Style {
        if self.scale {
            if size < 1024 {
                self.size.scale_byte
            }
            else if size < 1024 * 1024 {
                self.size.scale_kilo
            }
            else if size < 1024 * 1024 * 1024 {
                self.size.scale_mega
            }
            else if size < 1024 * 1024 * 1024 * 1024 {
                self.size.scale_giga
            }
            else {
                self.size.scale_huge
            }
        }
        else {
            self.size.numbers
        }
    }
}
<|endoftext|>