<commit_before>use std::io::{ErrorKind, Result};
use std::net::SocketAddr;
use std::thread;
use std::time::Duration;

use mio::net::{TcpListener, TcpStream};
use mio::{Evented, Events, Poll, PollOpt, Ready, Registration, Token};
use slab::Slab;

use birch::client::{ClientAuth, ClientConnection, ClientEvent};
use birch::network::NetworkConnection;
use birch::socket::{IrcSocketConfig, Socket};

// TODO: blah
type NetworkId = usize;
type ClientId = usize;

pub struct Ticker(Registration);

impl Ticker {
    pub fn new(interval: Duration) -> Self {
        let (registration, set_readiness) = Registration::new2();

        thread::spawn(move || loop {
            thread::sleep(interval);
            set_readiness.set_readiness(Ready::readable()).unwrap();
        });

        Self(registration)
    }
}

impl Evented for Ticker {
    fn register(
        &self,
        poll: &Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> Result<()> {
        self.0.register(poll, token, interest, opts)
    }

    fn reregister(
        &self,
        poll: &Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> Result<()> {
        self.0.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> Result<()> {
        poll.deregister(&self.0)
    }
}

struct Client {
    socket: Socket,
    conn: ClientConnection,
    network: Option<NetworkId>,
}

impl Client {
    fn from_stream(stream: TcpStream) -> Result<Self> {
        stream.set_keepalive(Some(Duration::from_secs(30)))?;

        let socket = Socket::from_stream(stream)?;
        let conn = ClientConnection::new();

        Ok(Self {
            socket,
            conn,
            network: None,
        })
    }
}

struct NetworkConfig {
    network_name: String,
    nick: String,
    socket: IrcSocketConfig,
    auth: (String, String),
}

impl NetworkConfig {
    fn create_socket(&self) -> Result<Socket> {
        let net_stream = std::net::TcpStream::connect(&self.socket.addr)?;
        let stream = TcpStream::from_stream(net_stream)?;

        // Make sure we send Keep Alive packets so that we can detect
        // e.g. the computer going to sleep.
        stream.set_keepalive(Some(Duration::from_secs(30)))?;

        Socket::from_stream(stream)
    }
}

struct Network {
    socket: Socket,
    conn: NetworkConnection,
    config: NetworkConfig,
    connected: bool,
}

impl Network {
    fn new(config: NetworkConfig) -> Result<Self> {
        let socket = config.create_socket()?;
        let conn = NetworkConnection::new(&config.nick);

        Ok(Self {
            socket,
            conn,
            config,
            connected: true,
        })
    }

    fn reconnect(&mut self) -> Result<()> {
        self.socket = self.config.create_socket()?;
        self.conn.initialize()?;
        self.connected = true;

        Ok(())
    }

    // TODO: blah, this could be better
    fn authenticate(&self, auth: &ClientAuth) -> bool {
        auth.network == self.config.network_name
            && auth.user == self.config.auth.0
            && auth.password == self.config.auth.1
    }
}

#[derive(PartialEq)]
enum SocketKind {
    Ticker,
    Listener,
    Network(NetworkId),
    Client(ClientId),
}

struct BirchServer {
    poll: Poll,
    sockets: Slab<SocketKind>,
    clients: Slab<Client>,
    // TODO: Since networks aren't dynamic, no benefit really to having this be a slab
    networks: Slab<Network>,
}

impl BirchServer {
    fn new() -> Self {
        Self {
            poll: Poll::new().expect("failed to create Poll instance"),
            sockets: Slab::with_capacity(1024),
            clients: Slab::with_capacity(32),
            networks: Slab::with_capacity(16),
        }
    }

    fn accept_client(&mut self, stream: TcpStream) -> Result<()> {
        let entry = self.clients.vacant_entry();

        let client_id = entry.key();
        let token = self.sockets.insert(SocketKind::Client(client_id));

        let client = Client::from_stream(stream)?;

        self.poll.register(
            &client.socket,
            Token(token),
            Ready::readable(),
            PollOpt::edge(),
        )?;

        entry.insert(client);

        println!("Client connected: client_id={} token={}", client_id, token);
        Ok(())
    }

    fn handle_network_message(&mut self, network_id: NetworkId) -> Result<()> {
        let network = self
            .networks
            .get_mut(network_id)
            .expect("activity on unassigned networks id");

        let msg = network.socket.read_message()?;

        println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
        network.conn.handle(&msg)?;

        for msg in network.conn.network_messages() {
            println!("[\u{1b}[37;1mbirch\u{1b}[0m -> net] {}", msg);
            network.socket.write_message(&msg)?;
        }

        for msg in network.conn.user_messages() {
            let clients = self
                .clients
                .iter_mut()
                .filter(|(_, c)| c.network == Some(network_id));

            for (_, client) in clients {
                if let Err(err) = client.socket.write_message(&msg) {
                    println!("Failed to write to client: {}", err);
                }
            }
        }

        Ok(())
    }

    fn handle_client_message(&mut self, client_id: ClientId) -> Result<()> {
        let client = self
            .clients
            .get_mut(client_id)
            .expect("activity on unassigned client id");

        let msg = client.socket.read_message()?;

        println!(
            "[birch <- \u{1b}[37;1mclient({})\u{1b}[0m] {}",
            client_id, msg
        );

        client.conn.handle_message(&msg)?;

        for event in client.conn.events() {
            match event {
                ClientEvent::WriteNetwork(ref _msg) => unimplemented!(),
                ClientEvent::WriteClient(ref msg) => client.socket.write_message(msg)?,
                ClientEvent::RegistrationComplete => {
                    // TODO: Update client's nick
                    match client.network {
                        Some(id) => {
                            let network = self
                                .networks
                                .get_mut(id)
                                .expect("client referencing unknown network");

                            network.conn.state.welcome_user(&mut client.socket)?;
                        }
                        None => panic!("registration completed without network"),
                    }
                }
                ClientEvent::AuthAttempt(auth) => {
                    let id = self
                        .networks
                        .iter()
                        .find(|(_, n)| n.authenticate(&auth))
                        .map(|(id, _)| id);

                    // TODO: set auth result back on client.conn
                    client.network = id
                }
            }
        }

        Ok(())
    }

    fn ping_clients(&mut self) -> Result<()> {
        let mut to_remove = Vec::new();
        for (id, client) in self.clients.iter_mut() {
            if !client.conn.ping() {
                println!("client({}) timed out", id);
                to_remove.push(id);
            }

            // TODO: remove duplication
            for event in client.conn.events() {
                match event {
                    ClientEvent::WriteClient(ref msg) => {
                        client.socket.write_message(msg)?
                    }
                    _ => unreachable!(),
                }
            }
        }

        for client_id in to_remove.iter() {
            self.remove_client(*client_id)?;
        }

        Ok(())
    }

    // TODO: This is a bit too complicated
    fn remove_client(&mut self, id: ClientId) -> Result<()> {
        let client = self.clients.remove(id);
        self.poll.deregister(&client.socket)?;

        let (tok, _) = self
            .sockets
            .iter()
            .find(|(_, s)| SocketKind::Client(id) == **s)
            .unwrap();

        self.sockets.remove(tok);
        Ok(())
    }

    fn reconnect_networks(&mut self) -> Result<()> {
        for (id, network) in self.networks.iter_mut().filter(|(_, n)| !n.connected) {
            println!("network {} is disconnected... attempting reconnect", id);
            match network.reconnect() {
                Ok(()) => self.poll.register(
                    &network.socket,
                    Token(self.sockets.insert(SocketKind::Network(id))),
                    Ready::readable(),
                    PollOpt::edge(),
                )?,
                Err(err) => println!("reconnect failed: {}", err),
            }
        }

        Ok(())
    }

    fn handle_poll_event(&mut self, listener: &TcpListener, token: Token) -> Result<()> {
        match self.sockets.get(token.0) {
            None => panic!("token not associated with a socket: {:?}", token),

            Some(&SocketKind::Ticker) => {
                self.ping_clients()?;
                self.reconnect_networks()?;
            }

            Some(&SocketKind::Listener) => loop {
                match listener.accept() {
                    Ok((socket, _)) => self.accept_client(socket)?,
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
                    e => panic!("failed to accept err={:?}", e),
                }
            },

            Some(&SocketKind::Network(network_id)) => loop {
                match self.handle_network_message(network_id) {
                    Ok(_) => (),
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
                    Err(e) => {
                        // TODO: Reconnection logic
                        println!("Network errored, disconnecting: {}", e);
                        self.sockets.remove(token.0);
                        let mut network = self.networks.get_mut(network_id).unwrap();
                        network.connected = false;
                        self.poll.deregister(&network.socket)?;
                        break;
                    }
                }
            },
            Some(&SocketKind::Client(client_id)) => loop {
                match self.handle_client_message(client_id) {
                    Ok(_) => (),
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
                    Err(e) => {
                        println!("Client errored, disconnecting: {}", e);
                        self.remove_client(client_id)?;
                        break;
                    }
                }
            },
        }

        Ok(())
    }

    fn add_network(&mut self, config: NetworkConfig) -> Result<NetworkId> {
        let mut network = Network::new(config)?;
        network.conn.initialize()?;

        let token = self.networks.insert(network);
        self.sockets.insert(SocketKind::Network(token));

        Ok(token)
    }

    fn serve(&mut self, bind_addr: &SocketAddr) -> Result<()> {
        // TODO: is this iffy? Should we just store the Poll object on
        // the struct itself?
        for (id, network) in self.networks.iter_mut() {
            self.poll.register(
                &network.socket,
                Token(id),
                Ready::readable(),
                PollOpt::edge(),
            )?;
        }

        let listener = TcpListener::bind(bind_addr)?;
        {
            let tok = self.sockets.insert(SocketKind::Listener);
            self.poll.register(
                &listener,
                Token(tok),
                Ready::readable(),
                PollOpt::edge(),
            )?;
        }

        let ticker = Ticker::new(Duration::from_secs(60));
        {
            let tok = self.sockets.insert(SocketKind::Ticker);
            self.poll.register(
                &ticker,
                Token(tok),
                Ready::readable(),
                PollOpt::edge(),
            )?;
        }

        loop {
            let mut events = Events::with_capacity(128);
            self.poll.poll(&mut events, None)?;

            for ev in events {
                self.handle_poll_event(&listener, ev.token())?;
            }
        }
    }
}

fn main() -> Result<()> {
    let config = NetworkConfig {
        network_name: "freenode".to_string(),
        nick: "ep".to_string(),
        auth: ("foo".to_string(), "bar".to_string()),
        socket: IrcSocketConfig {
            addr: "irc.freenode.net:6667".parse().unwrap(),
            max_retries: Some(3),
        },
    };

    let mut server = BirchServer::new();
    server.add_network(config)?;

    server.serve(&"127.0.0.1:9123".parse().unwrap())
}
<commit_msg>Minor clean up<commit_after>use std::io::{ErrorKind, Result};
use std::net::SocketAddr;
use std::thread;
use std::time::Duration;

use mio::net::{TcpListener, TcpStream};
use mio::{Evented, Events, Poll, PollOpt, Ready, Registration, Token};
use slab::Slab;

use birch::client::{ClientAuth, ClientConnection, ClientEvent};
use birch::network::NetworkConnection;
use birch::socket::{IrcSocketConfig, Socket};

// TODO: blah
type NetworkId = usize;
type ClientId = usize;

pub struct Ticker(Registration);

impl Ticker {
    pub fn new(interval: Duration) -> Self {
        let (registration, set_readiness) = Registration::new2();

        thread::spawn(move || loop {
            thread::sleep(interval);
            set_readiness.set_readiness(Ready::readable()).unwrap();
        });

        Self(registration)
    }
}

impl Evented for Ticker {
    fn register(
        &self,
        poll: &Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> Result<()> {
        self.0.register(poll, token, interest, opts)
    }

    fn reregister(
        &self,
        poll: &Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> Result<()> {
        self.0.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> Result<()> {
        poll.deregister(&self.0)
    }
}

struct Client {
    socket: Socket,
    conn: ClientConnection,
    network: Option<NetworkId>,
}

impl Client {
    fn from_stream(stream: TcpStream) -> Result<Self> {
        stream.set_keepalive(Some(Duration::from_secs(30)))?;

        let socket = Socket::from_stream(stream)?;
        let conn = ClientConnection::new();

        Ok(Self {
            socket,
            conn,
            network: None,
        })
    }
}

struct NetworkConfig {
    network_name: String,
    nick: String,
    socket: IrcSocketConfig,
    auth: (String, String),
}

impl NetworkConfig {
    fn create_socket(&self) -> Result<Socket> {
        let net_stream = std::net::TcpStream::connect(&self.socket.addr)?;
        let stream = TcpStream::from_stream(net_stream)?;

        // Make sure we send Keep Alive packets so that we can detect
        // e.g. the computer going to sleep.
        stream.set_keepalive(Some(Duration::from_secs(30)))?;

        Socket::from_stream(stream)
    }
}

struct Network {
    socket: Socket,
    conn: NetworkConnection,
    config: NetworkConfig,
    connected: bool,
}

impl Network {
    fn new(config: NetworkConfig) -> Result<Self> {
        let socket = config.create_socket()?;
        let conn = NetworkConnection::new(&config.nick);

        Ok(Self {
            socket,
            conn,
            config,
            connected: true,
        })
    }

    fn reconnect(&mut self) -> Result<()> {
        self.socket = self.config.create_socket()?;
        self.conn.initialize()?;
        self.connected = true;

        Ok(())
    }

    // TODO: blah, this could be better
    fn authenticate(&self, auth: &ClientAuth) -> bool {
        auth.network == self.config.network_name
            && auth.user == self.config.auth.0
            && auth.password == self.config.auth.1
    }
}

#[derive(PartialEq)]
enum SocketKind {
    Ticker,
    Listener,
    Network(NetworkId),
    Client(ClientId),
}

struct BirchServer {
    poll: Poll,
    sockets: Slab<SocketKind>,
    clients: Slab<Client>,
    // TODO: Since networks aren't dynamic, no benefit really to having this be a slab
    networks: Slab<Network>,
}

impl BirchServer {
    fn new() -> Self {
        Self {
            poll: Poll::new().expect("failed to create Poll instance"),
            sockets: Slab::with_capacity(1024),
            clients: Slab::with_capacity(32),
            networks: Slab::with_capacity(16),
        }
    }

    fn accept_client(&mut self, stream: TcpStream) -> Result<()> {
        let entry = self.clients.vacant_entry();

        let client_id = entry.key();
        let token = self.sockets.insert(SocketKind::Client(client_id));

        let client = Client::from_stream(stream)?;

        self.poll.register(
            &client.socket,
            Token(token),
            Ready::readable(),
            PollOpt::edge(),
        )?;

        entry.insert(client);

        println!("Client connected: client_id={} token={}", client_id, token);
        Ok(())
    }

    fn handle_network_message(&mut self, network_id: NetworkId) -> Result<()> {
        let network = self
            .networks
            .get_mut(network_id)
            .expect("activity on unassigned networks id");

        let msg = network.socket.read_message()?;

        println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
        network.conn.handle(&msg)?;

        for msg in network.conn.network_messages() {
            println!("[\u{1b}[37;1mbirch\u{1b}[0m -> net] {}", msg);
            network.socket.write_message(&msg)?;
        }

        for msg in network.conn.user_messages() {
            let clients = self
                .clients
                .iter_mut()
                .filter(|(_, c)| c.network == Some(network_id));

            for (_, client) in clients {
                if let Err(err) = client.socket.write_message(&msg) {
                    println!("Failed to write to client: {}", err);
                }
            }
        }

        Ok(())
    }

    fn handle_client_message(&mut self, client_id: ClientId) -> Result<()> {
        let client = self
            .clients
            .get_mut(client_id)
            .expect("activity on unassigned client id");

        let msg = client.socket.read_message()?;

        println!(
            "[birch <- \u{1b}[37;1mclient({})\u{1b}[0m] {}",
            client_id, msg
        );

        client.conn.handle_message(&msg)?;

        for event in client.conn.events() {
            match event {
                ClientEvent::WriteNetwork(ref _msg) => unimplemented!(),
                ClientEvent::WriteClient(ref msg) => client.socket.write_message(msg)?,
                ClientEvent::RegistrationComplete => {
                    // TODO: Update client's nick
                    match client.network {
                        Some(id) => {
                            let network = self
                                .networks
                                .get_mut(id)
                                .expect("client referencing unknown network");

                            network.conn.state.welcome_user(&mut client.socket)?;
                        }
                        None => panic!("registration completed without network"),
                    }
                }
                ClientEvent::AuthAttempt(auth) => {
                    let id = self
                        .networks
                        .iter()
                        .find(|(_, n)| n.authenticate(&auth))
                        .map(|(id, _)| id);

                    // TODO: set auth result back on client.conn
                    client.network = id
                }
            }
        }

        Ok(())
    }

    fn ping_clients(&mut self) -> Result<()> {
        let mut to_remove = Vec::new();
        for (id, client) in self.clients.iter_mut() {
            if !client.conn.ping() {
                println!("client({}) timed out", id);
                to_remove.push(id);
            }

            // TODO: remove duplication
            for event in client.conn.events() {
                match event {
                    ClientEvent::WriteClient(ref msg) => {
                        client.socket.write_message(msg)?
                    }
                    _ => unreachable!(),
                }
            }
        }

        for client_id in to_remove.iter() {
            self.remove_client(*client_id)?;
        }

        Ok(())
    }

    // TODO: This is a bit too complicated
    fn remove_client(&mut self, id: ClientId) -> Result<()> {
        let client = self.clients.remove(id);
        self.poll.deregister(&client.socket)?;

        let (tok, _) = self
            .sockets
            .iter()
            .find(|(_, s)| SocketKind::Client(id) == **s)
            .unwrap();

        self.sockets.remove(tok);
        Ok(())
    }

    fn reconnect_networks(&mut self) -> Result<()> {
        for (id, network) in self.networks.iter_mut().filter(|(_, n)| !n.connected) {
            println!("network {} is disconnected... attempting reconnect", id);
            match network.reconnect() {
                Ok(()) => self.poll.register(
                    &network.socket,
                    Token(self.sockets.insert(SocketKind::Network(id))),
                    Ready::readable(),
                    PollOpt::edge(),
                )?,
                Err(err) => println!("reconnect failed: {}", err),
            }
        }

        Ok(())
    }

    fn handle_poll_event(&mut self, listener: &TcpListener, token: Token) -> Result<()> {
        match self.sockets.get(token.0) {
            None => panic!("token not associated with a socket: {:?}", token),

            Some(&SocketKind::Ticker) => {
                self.ping_clients()?;
                self.reconnect_networks()?;
            }

            Some(&SocketKind::Listener) => loop {
                match listener.accept() {
                    Ok((socket, _)) => self.accept_client(socket)?,
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
                    e => panic!("failed to accept err={:?}", e),
                }
            },

            Some(&SocketKind::Network(network_id)) => loop {
                match self.handle_network_message(network_id) {
                    Ok(_) => (),
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
                    Err(e) => {
                        println!("Network errored, disconnecting: {}", e);
                        self.sockets.remove(token.0);
                        let mut network = self.networks.get_mut(network_id).unwrap();
                        network.connected = false;
                        self.poll.deregister(&network.socket)?;
                        break;
                    }
                }
            },
            Some(&SocketKind::Client(client_id)) => loop {
                match self.handle_client_message(client_id) {
                    Ok(_) => (),
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
                    Err(e) => {
                        println!("Client errored, disconnecting: {}", e);
                        self.remove_client(client_id)?;
                        break;
                    }
                }
            },
        }

        Ok(())
    }

    fn add_network(&mut self, config: NetworkConfig) -> Result<NetworkId> {
        let mut network = Network::new(config)?;
        network.conn.initialize()?;

        let entry = self.networks.vacant_entry();
        let network_id = entry.key();
        let id = self.sockets.insert(SocketKind::Network(network_id));

        self.poll.register(
            &network.socket,
            Token(id),
            Ready::readable(),
            PollOpt::edge(),
        )?;

        entry.insert(network);
        Ok(network_id)
    }

    fn serve(&mut self, bind_addr: &SocketAddr) -> Result<()> {
        let listener = TcpListener::bind(bind_addr)?;
        {
            let tok = self.sockets.insert(SocketKind::Listener);
            self.poll.register(
                &listener,
                Token(tok),
                Ready::readable(),
                PollOpt::edge(),
            )?;
        }

        {
            let ticker = Ticker::new(Duration::from_secs(60));
            let tok = self.sockets.insert(SocketKind::Ticker);
            self.poll.register(
                &ticker,
                Token(tok),
                Ready::readable(),
                PollOpt::edge(),
            )?;
        }

        loop {
            let mut events = Events::with_capacity(128);
            self.poll.poll(&mut events, None)?;

            for ev in events {
                self.handle_poll_event(&listener, ev.token())?;
            }
        }
    }
}

fn main() -> Result<()> {
    let config = NetworkConfig {
        network_name: "freenode".to_string(),
        nick: "ep".to_string(),
        auth: ("foo".to_string(), "bar".to_string()),
        socket: IrcSocketConfig {
            addr: "irc.freenode.net:6667".parse().unwrap(),
            max_retries: Some(3),
        },
    };

    let mut server = BirchServer::new();
    server.add_network(config)?;

    server.serve(&"127.0.0.1:9123".parse().unwrap())
}
<|endoftext|>


<commit_before>use std::error::Error;
use postgres::types::{FromSql, IsNull, ToSql, Type, CIDR};
use postgres::{accepts, to_sql_checked};
use crate::{IpNetwork, Ipv4Network, Ipv6Network};
use crate::postgres_common;

impl ToSql for Ipv4Network {
    fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
        let bytes = postgres_common::to_sql_ipv4_network(*self);
        w.extend_from_slice(&bytes);

        Ok(IsNull::No)
    }

    accepts!(CIDR);
    to_sql_checked!();
}

impl ToSql for Ipv6Network {
    fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
        let bytes = postgres_common::to_sql_ipv6_network(*self);
        w.extend_from_slice(&bytes);

        Ok(IsNull::No)
    }

    accepts!(CIDR);
    to_sql_checked!();
}

impl FromSql for Ipv4Network {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Ipv4Network, Box<Error + Sync + Send>> {
        postgres_common::from_sql_ipv4_network(raw)
    }

    accepts!(CIDR);
}

impl FromSql for Ipv6Network {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Ipv6Network, Box<Error + Sync + Send>> {
        postgres_common::from_sql_ipv6_network(raw)
    }

    accepts!(CIDR);
}

impl FromSql for IpNetwork {
    fn from_sql(t: &Type, raw: &[u8]) -> Result<IpNetwork, Box<Error + Sync + Send>> {
        match raw[0] {
            postgres_common::IPV4_TYPE => Ok(IpNetwork::V4(Ipv4Network::from_sql(t, raw)?)),
            postgres_common::IPV6_TYPE => Ok(IpNetwork::V6(Ipv6Network::from_sql(t, raw)?)),
            _ => Err("CIDR is not IP version 4 or 6".into()),
        }
    }

    accepts!(CIDR);
}

impl ToSql for IpNetwork {
    fn to_sql(&self, t: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
        match *self {
            IpNetwork::V4(ref network) => network.to_sql(t, w),
            IpNetwork::V6(ref network) => network.to_sql(t, w),
        }
    }

    accepts!(CIDR);
    to_sql_checked!();
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use postgres::types::{FromSql, ToSql, CIDR};
    use crate::{IpNetwork, Ipv4Network, Ipv6Network};

    fn return_test_ipv4_network() -> Ipv4Network {
        Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 16).unwrap()
    }

    fn return_test_ipv6_network() -> Ipv6Network {
        Ipv6Network::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0), 32).unwrap()
    }

    #[test]
    fn ivp4_to_sql() {
        let ip_network = return_test_ipv4_network();
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
        assert_eq!(2, output[0]);
        assert_eq!(16, output[1]);
        assert_eq!(1, output[2]);
        assert_eq!(4, output[3]);
        assert_eq!(192, output[4]);
        assert_eq!(168, output[5]);
        assert_eq!(0, output[6]);
        assert_eq!(0, output[7]);
    }

    #[test]
    fn ivp4_both_direction() {
        let ip_network = return_test_ipv4_network();
        let mut output = vec![];

        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());

        let result = Ipv4Network::from_sql(&CIDR, &output);
        assert!(result.is_ok());

        let ip_network_converted = result.unwrap();
        assert_eq!(ip_network, ip_network_converted);
    }

    #[test]
    fn ivp6_to_sql() {
        let ip_network = return_test_ipv6_network();
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
        assert_eq!(3, output[0]);
        assert_eq!(32, output[1]);
        assert_eq!(1, output[2]);
        assert_eq!(16, output[3]);
        // TODO: IPv6 comparsion
    }

    #[test]
    fn ivp6_both_direction() {
        let ip_network = return_test_ipv6_network();
        let mut output = vec![];

        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());

        let result = Ipv6Network::from_sql(&CIDR, &output);
        assert!(result.is_ok());

        let ip_network_converted = result.unwrap();
        assert_eq!(ip_network, ip_network_converted);
    }

    #[test]
    fn ipnetwork_to_sql_v4() {
        let ip_network = IpNetwork::V4(return_test_ipv4_network());
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
    }

    #[test]
    fn ipnetwork_to_sql_v6() {
        let ip_network = IpNetwork::V6(return_test_ipv6_network());
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
    }
}
<commit_msg>Simplified Postgres support code<commit_after>use std::error::Error;
use postgres::types::{FromSql, IsNull, ToSql, Type, CIDR};
use postgres::{accepts, to_sql_checked};
use crate::{IpNetwork, Ipv4Network, Ipv6Network};
use crate::postgres_common;

type PostgresResult<T> = Result<T, Box<Error + Sync + Send>>;

impl FromSql for Ipv4Network {
    fn from_sql(_: &Type, raw: &[u8]) -> PostgresResult<Ipv4Network> {
        postgres_common::from_sql_ipv4_network(raw)
    }

    accepts!(CIDR);
}

impl FromSql for Ipv6Network {
    fn from_sql(_: &Type, raw: &[u8]) -> PostgresResult<Ipv6Network> {
        postgres_common::from_sql_ipv6_network(raw)
    }

    accepts!(CIDR);
}

impl FromSql for IpNetwork {
    fn from_sql(t: &Type, raw: &[u8]) -> PostgresResult<IpNetwork> {
        match raw[0] {
            postgres_common::IPV4_TYPE => Ok(IpNetwork::V4(Ipv4Network::from_sql(t, raw)?)),
            postgres_common::IPV6_TYPE => Ok(IpNetwork::V6(Ipv6Network::from_sql(t, raw)?)),
            _ => Err("CIDR is not IP version 4 or 6".into()),
        }
    }

    accepts!(CIDR);
}

impl ToSql for Ipv4Network {
    fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> PostgresResult<IsNull> {
        let bytes = postgres_common::to_sql_ipv4_network(*self);
        w.extend_from_slice(&bytes);

        Ok(IsNull::No)
    }

    accepts!(CIDR);
    to_sql_checked!();
}

impl ToSql for Ipv6Network {
    fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> PostgresResult<IsNull> {
        let bytes = postgres_common::to_sql_ipv6_network(*self);
        w.extend_from_slice(&bytes);

        Ok(IsNull::No)
    }

    accepts!(CIDR);
    to_sql_checked!();
}

impl ToSql for IpNetwork {
    fn to_sql(&self, t: &Type, w: &mut Vec<u8>) -> PostgresResult<IsNull> {
        match *self {
            IpNetwork::V4(ref network) => network.to_sql(t, w),
            IpNetwork::V6(ref network) => network.to_sql(t, w),
        }
    }

    accepts!(CIDR);
    to_sql_checked!();
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use postgres::types::{FromSql, ToSql, CIDR};
    use crate::{IpNetwork, Ipv4Network, Ipv6Network};

    fn return_test_ipv4_network() -> Ipv4Network {
        Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 16).unwrap()
    }

    fn return_test_ipv6_network() -> Ipv6Network {
        Ipv6Network::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0), 32).unwrap()
    }

    #[test]
    fn ivp4_to_sql() {
        let ip_network = return_test_ipv4_network();
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
        assert_eq!(2, output[0]);
        assert_eq!(16, output[1]);
        assert_eq!(1, output[2]);
        assert_eq!(4, output[3]);
        assert_eq!(192, output[4]);
        assert_eq!(168, output[5]);
        assert_eq!(0, output[6]);
        assert_eq!(0, output[7]);
    }

    #[test]
    fn ivp4_both_direction() {
        let ip_network = return_test_ipv4_network();
        let mut output = vec![];

        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());

        let result = Ipv4Network::from_sql(&CIDR, &output);
        assert!(result.is_ok());

        let ip_network_converted = result.unwrap();
        assert_eq!(ip_network, ip_network_converted);
    }

    #[test]
    fn ivp6_to_sql() {
        let ip_network = return_test_ipv6_network();
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
        assert_eq!(3, output[0]);
        assert_eq!(32, output[1]);
        assert_eq!(1, output[2]);
        assert_eq!(16, output[3]);
        // TODO: IPv6 comparsion
    }

    #[test]
    fn ivp6_both_direction() {
        let ip_network = return_test_ipv6_network();
        let mut output = vec![];

        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());

        let result = Ipv6Network::from_sql(&CIDR, &output);
        assert!(result.is_ok());

        let ip_network_converted = result.unwrap();
        assert_eq!(ip_network, ip_network_converted);
    }

    #[test]
    fn ipnetwork_to_sql_v4() {
        let ip_network = IpNetwork::V4(return_test_ipv4_network());
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
    }

    #[test]
    fn ipnetwork_to_sql_v6() {
        let ip_network = IpNetwork::V6(return_test_ipv6_network());
        let mut output = vec![];
        assert!(ip_network.to_sql(&CIDR, &mut output).is_ok());
    }
}
<|endoftext|>


<commit_before>//! Higher-level Rust constructs for http_parser

export HttpCallback, HttpDataCallback;
export ParserCallbacks, Parser;

use vec::raw::from_buf;
use libc::{c_int, c_void, c_char, size_t};
use ptr::{null, to_unsafe_ptr};
use http_parser::{
    http_parser, http_parser_settings, HTTP_RESPONSE
};
use http_parser::bindgen::{http_parser_init, http_parser_execute};

type HttpCallback = fn@() -> bool;
type HttpDataCallback = fn@(data: ~[u8]) -> bool;

type ParserCallbacks = {
    on_message_begin: HttpCallback,
    on_url: HttpDataCallback,
    on_header_field: HttpDataCallback,
    on_header_value: HttpDataCallback,
    on_headers_complete: HttpCallback,
    on_body: HttpDataCallback,
    on_message_complete: HttpCallback
};

struct Parser {
    mut http_parser: http_parser,
    settings: http_parser_settings
}

fn Parser() -> Parser {
    let http_parser = {
        _type_flags: 0,
        state: 0,
        header_state: 0,
        index: 0,
        nread: 0,
        content_length: 0,
        http_major: 0,
        http_minor: 0,
        status_code: 0,
        method: 0,
        http_errno_upgrade: 0,
        data: null()
    };

    http_parser_init(to_unsafe_ptr(&http_parser), HTTP_RESPONSE);

    let settings = {
        on_message_begin: on_message_begin,
        on_url: on_url,
        on_header_field: on_header_field,
        on_header_value: on_header_value,
        on_headers_complete: on_headers_complete,
        on_body: on_body,
        on_message_complete: on_message_complete
    };

    Parser {
        http_parser: move http_parser,
        settings: move settings
    }
}

impl Parser {
    fn execute(data: &[u8], callbacks: &ParserCallbacks) -> uint {
        self.http_parser.data = to_unsafe_ptr(callbacks) as *c_void;
        do vec::as_imm_buf(data) |buf, _i| {
            http_parser_execute(to_unsafe_ptr(&self.http_parser),
                                to_unsafe_ptr(&self.settings),
                                buf as *c_char, data.len() as size_t) as uint
        }
    }

    fn status_code() -> uint {
        self.http_parser.status_code as uint
    }
}

fn callbacks(http_parser: *http_parser) -> *ParserCallbacks {
    unsafe {
        assert (*http_parser).data.is_not_null();
        return (*http_parser).data as *ParserCallbacks;
    }
}

extern fn on_message_begin(http_parser: *http_parser) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_message_begin()) as c_int
    }
}

extern fn on_url(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_url(from_buf(at, length as uint))) as c_int
    }
}

extern fn on_header_field(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_header_field(from_buf(at, length as uint))) as c_int
    }
}

extern fn on_header_value(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_header_value(from_buf(at, length as uint))) as c_int
    }
}

extern fn on_headers_complete(http_parser: *http_parser) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_headers_complete()) as c_int
    }
}

extern fn on_body(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_body(from_buf(at, length as uint))) as c_int
    }
}

extern fn on_message_complete(http_parser: *http_parser) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_message_complete()) as c_int
    }
}
<commit_msg>Update for library changes<commit_after>//! Higher-level Rust constructs for http_parser

export HttpCallback, HttpDataCallback;
export ParserCallbacks, Parser;

use vec::raw::from_buf_raw;
use libc::{c_int, c_void, c_char, size_t};
use ptr::{null, to_unsafe_ptr};
use http_parser::{
    http_parser, http_parser_settings, HTTP_RESPONSE
};
use http_parser::bindgen::{http_parser_init, http_parser_execute};

type HttpCallback = fn@() -> bool;
type HttpDataCallback = fn@(data: ~[u8]) -> bool;

type ParserCallbacks = {
    on_message_begin: HttpCallback,
    on_url: HttpDataCallback,
    on_header_field: HttpDataCallback,
    on_header_value: HttpDataCallback,
    on_headers_complete: HttpCallback,
    on_body: HttpDataCallback,
    on_message_complete: HttpCallback
};

struct Parser {
    mut http_parser: http_parser,
    settings: http_parser_settings
}

fn Parser() -> Parser {
    let http_parser = {
        _type_flags: 0,
        state: 0,
        header_state: 0,
        index: 0,
        nread: 0,
        content_length: 0,
        http_major: 0,
        http_minor: 0,
        status_code: 0,
        method: 0,
        http_errno_upgrade: 0,
        data: null()
    };

    http_parser_init(to_unsafe_ptr(&http_parser), HTTP_RESPONSE);

    let settings = {
        on_message_begin: on_message_begin,
        on_url: on_url,
        on_header_field: on_header_field,
        on_header_value: on_header_value,
        on_headers_complete: on_headers_complete,
        on_body: on_body,
        on_message_complete: on_message_complete
    };

    Parser {
        http_parser: move http_parser,
        settings: move settings
    }
}

impl Parser {
    fn execute(data: &[u8], callbacks: &ParserCallbacks) -> uint {
        self.http_parser.data = to_unsafe_ptr(callbacks) as *c_void;
        do vec::as_imm_buf(data) |buf, _i| {
            http_parser_execute(to_unsafe_ptr(&self.http_parser),
                                to_unsafe_ptr(&self.settings),
                                buf as *c_char, data.len() as size_t) as uint
        }
    }

    fn status_code() -> uint {
        self.http_parser.status_code as uint
    }
}

fn callbacks(http_parser: *http_parser) -> *ParserCallbacks {
    unsafe {
        assert (*http_parser).data.is_not_null();
        return (*http_parser).data as *ParserCallbacks;
    }
}

extern fn on_message_begin(http_parser: *http_parser) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_message_begin()) as c_int
    }
}

extern fn on_url(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_url(from_buf_raw(at, length as uint))) as c_int
    }
}

extern fn on_header_field(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_header_field(from_buf_raw(at, length as uint))) as c_int
    }
}

extern fn on_header_value(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_header_value(from_buf_raw(at, length as uint))) as c_int
    }
}

extern fn on_headers_complete(http_parser: *http_parser) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_headers_complete()) as c_int
    }
}

extern fn on_body(http_parser: *http_parser, at: *u8, length: size_t) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_body(from_buf_raw(at, length as uint))) as c_int
    }
}

extern fn on_message_complete(http_parser: *http_parser) -> c_int {
    unsafe {
        (!(*callbacks(http_parser)).on_message_complete()) as c_int
    }
}
<|endoftext|>


<commit_before>/*
 * UpdateHub
 * Copyright (C) 2017
 * O.S. Systems Sofware LTDA: contact@ossystems.com.br
 *
 * SPDX-License-Identifier:     GPL-2.0
 */

use serde_ini;

extern crate chrono;
use self::chrono::{DateTime, Utc};

use std::io;

use de_helpers::bool_from_str;

#[derive(Default, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimeSettings {
    pub polling: RuntimePolling,
    pub update: RuntimeUpdate,
}

impl RuntimeSettings {
    pub fn new() -> Self {
        RuntimeSettings::default()
    }

    pub fn load(self, path: &str) -> Result<Self, RuntimeSettingsError> {
        use std::fs::File;
        use std::io::Read;
        use std::path::Path;

        let path = Path::new(path);

        if path.exists() {
            info!(
                "Loading runtime settings from '{}'...",
                path.to_string_lossy()
            );

            let mut content = String::new();
            File::open(path)?.read_to_string(&mut content)?;

            Ok(self.parse(&content)?)
        } else {
            debug!(
                "Runtime settings file {} does not exists.",
                path.to_string_lossy()
            );
            info!("Using default runtime settings...");
            Ok(self)
        }
    }

    fn parse(self, content: &str) -> Result<Self, RuntimeSettingsError> {
        Ok(serde_ini::from_str::<RuntimeSettings>(content)?)
    }
}

#[derive(Debug)]
pub enum RuntimeSettingsError {
    Io(io::Error),
    Ini(serde_ini::de::Error),
}

impl From<io::Error> for RuntimeSettingsError {
    fn from(err: io::Error) -> RuntimeSettingsError {
        RuntimeSettingsError::Io(err)
    }
}

impl From<serde_ini::de::Error> for RuntimeSettingsError {
    fn from(err: serde_ini::de::Error) -> RuntimeSettingsError {
        RuntimeSettingsError::Ini(err)
    }
}

#[derive(Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimePolling {
    #[serde(rename = "LastPoll")]
    pub last: DateTime<Utc>,
    #[serde(rename = "FirstPoll")]
    pub first: DateTime<Utc>,
    pub extra_interval: usize,
    pub retries: usize,
    #[serde(rename = "ProbeASAP")]
    #[serde(deserialize_with = "bool_from_str")]
    pub now: bool,
}

impl Default for RuntimePolling {
    fn default() -> Self {
        RuntimePolling {
            last: Utc::now(),
            first: Utc::now(),
            extra_interval: 0,
            retries: 0,
            now: false,
        }
    }
}

#[derive(Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimeUpdate {
    #[serde(rename = "UpgradeToInstallation")]
    pub upgrading_to: i8,
}

impl Default for RuntimeUpdate {
    fn default() -> Self {
        RuntimeUpdate { upgrading_to: -1 }
    }
}

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

    #[test]
    fn ok() {
        let ini = r"
[Polling]
LastPoll=2017-01-01T00:00:00Z
FirstPoll=2017-02-02T00:00:00Z
ExtraInterval=4
Retries=5
ProbeASAP=false

[Update]
UpgradeToInstallation=1
";
        let expected = RuntimeSettings {
            polling: RuntimePolling {
                last: "2017-01-01T00:00:00Z".parse::<DateTime<Utc>>().unwrap(),
                first: "2017-02-02T00:00:00Z".parse::<DateTime<Utc>>().unwrap(),
                extra_interval: 4,
                retries: 5,
                now: false,
            },
            update: RuntimeUpdate { upgrading_to: 1 },
        };

        assert!(
            serde_ini::from_str::<RuntimeSettings>(&ini)
                .map_err(|e| println!("{}", e))
                .as_ref()
                .ok() == Some(&expected)
        );
        assert!(RuntimeSettings::new().parse(&ini).as_ref().ok() == Some(&expected));
    }

    #[test]
    fn default() {
        let settings = RuntimeSettings::new();
        let expected = RuntimeSettings {
            polling: RuntimePolling {
                last: settings.polling.last,
                first: settings.polling.first,
                extra_interval: 0,
                retries: 0,
                now: false,
            },
            update: RuntimeUpdate { upgrading_to: -1 },
        };

        assert!(Some(settings) == Some(expected));
    }
}
<commit_msg>runtime_settings: Fix load to store the path in all cases<commit_after>/*
 * UpdateHub
 * Copyright (C) 2017
 * O.S. Systems Sofware LTDA: contact@ossystems.com.br
 *
 * SPDX-License-Identifier:     GPL-2.0
 */

use serde_ini;

extern crate chrono;
use self::chrono::{DateTime, Utc};

use std::io;

use de_helpers::bool_from_str;

#[derive(Default, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimeSettings {
    pub polling: RuntimePolling,
    pub update: RuntimeUpdate,
}

impl RuntimeSettings {
    pub fn new() -> Self {
        RuntimeSettings::default()
    }

    pub fn load(mut self, path: &str) -> Result<Self, RuntimeSettingsError> {
        use std::fs::File;
        use std::io::Read;
        use std::path::Path;

        let path = Path::new(path);

        if path.exists() {
            info!(
                "Loading runtime settings from '{}'...",
                path.to_string_lossy()
            );

            let mut content = String::new();
            File::open(path)?.read_to_string(&mut content)?;
            self = self.parse(&content)?;
        } else {
            debug!(
                "Runtime settings file {} does not exists.",
                path.to_string_lossy()
            );
            info!("Using default runtime settings...");
        }

        self.path = path.to_path_buf();
        Ok(self)
    }

    fn parse(self, content: &str) -> Result<Self, RuntimeSettingsError> {
        Ok(serde_ini::from_str::<RuntimeSettings>(content)?)
    }
}

#[derive(Debug)]
pub enum RuntimeSettingsError {
    Io(io::Error),
    Ini(serde_ini::de::Error),
}

impl From<io::Error> for RuntimeSettingsError {
    fn from(err: io::Error) -> RuntimeSettingsError {
        RuntimeSettingsError::Io(err)
    }
}

impl From<serde_ini::de::Error> for RuntimeSettingsError {
    fn from(err: serde_ini::de::Error) -> RuntimeSettingsError {
        RuntimeSettingsError::Ini(err)
    }
}

#[derive(Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimePolling {
    #[serde(rename = "LastPoll")]
    pub last: DateTime<Utc>,
    #[serde(rename = "FirstPoll")]
    pub first: DateTime<Utc>,
    pub extra_interval: usize,
    pub retries: usize,
    #[serde(rename = "ProbeASAP")]
    #[serde(deserialize_with = "bool_from_str")]
    pub now: bool,
}

impl Default for RuntimePolling {
    fn default() -> Self {
        RuntimePolling {
            last: Utc::now(),
            first: Utc::now(),
            extra_interval: 0,
            retries: 0,
            now: false,
        }
    }
}

#[derive(Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct RuntimeUpdate {
    #[serde(rename = "UpgradeToInstallation")]
    pub upgrading_to: i8,
}

impl Default for RuntimeUpdate {
    fn default() -> Self {
        RuntimeUpdate { upgrading_to: -1 }
    }
}

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

    #[test]
    fn ok() {
        let ini = r"
[Polling]
LastPoll=2017-01-01T00:00:00Z
FirstPoll=2017-02-02T00:00:00Z
ExtraInterval=4
Retries=5
ProbeASAP=false

[Update]
UpgradeToInstallation=1
";
        let expected = RuntimeSettings {
            polling: RuntimePolling {
                last: "2017-01-01T00:00:00Z".parse::<DateTime<Utc>>().unwrap(),
                first: "2017-02-02T00:00:00Z".parse::<DateTime<Utc>>().unwrap(),
                extra_interval: 4,
                retries: 5,
                now: false,
            },
            update: RuntimeUpdate { upgrading_to: 1 },
        };

        assert!(
            serde_ini::from_str::<RuntimeSettings>(&ini)
                .map_err(|e| println!("{}", e))
                .as_ref()
                .ok() == Some(&expected)
        );
        assert!(RuntimeSettings::new().parse(&ini).as_ref().ok() == Some(&expected));
    }

    #[test]
    fn default() {
        let settings = RuntimeSettings::new();
        let expected = RuntimeSettings {
            polling: RuntimePolling {
                last: settings.polling.last,
                first: settings.polling.first,
                extra_interval: 0,
                retries: 0,
                now: false,
            },
            update: RuntimeUpdate { upgrading_to: -1 },
        };

        assert!(Some(settings) == Some(expected));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::thread;
use std::thread::JoinHandle;
use std::net::TcpStream;
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError
};

use super::types::*;
use super::epoll;
use super::epoll::util::*;
use super::epoll::EpollEvent;
use super::socket::Socket;
use super::simple_stream::nbetstream::NbetStream;

#[allow(dead_code)]
pub struct EventLoop {
    /// Handle to event loop process
    prox: JoinHandle<()>,
    /// Sender<T> to proc
    prox_tx: Sender<TcpStream>
}

impl EventLoop {

    /// Returns a new EventLoop
    pub fn new(server_tx: Sender<EventTuple>) -> EventLoop {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();
        let prox = thread::Builder::new()
            .name("EventLoop".to_string())
            .spawn(move || {
                EventLoop::start(rx, server_tx);
            }).unwrap();

        EventLoop {
            prox: prox,
            prox_tx: tx
        }
    }

    /// Returns a clone of this EventLoop's Sender<TcpStream> channel
    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    /// Main event loop
    fn start(rx: Receiver<TcpStream>, uspace_tx: Sender<EventTuple>) {
        // Master socket list
        let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

        // Our error handler for this thread and it's children
        let (err_tx, err_rx): (Sender<()>, Receiver<()>) = channel();

        // Create an epoll instance
        let result = epoll::create1(0);
        if result.is_err() {
            let err = result.unwrap_err();
            panic!("Unable to create epoll instance: {}", err)
        }
        let epoll_instance = result.unwrap();

        // Start the epoll thread
        let c_sockets = sockets.clone();
        let c_epoll_instance = epoll_instance.clone();
        let epoll_prox = thread::Builder::new()
            .name("EpollLoop".to_string())
            .spawn(move || {
                EventLoop::epoll_loop(uspace_tx, c_sockets, c_epoll_instance, err_rx);
            }).unwrap();

        for new_stream in rx.iter() {
            match NbetStream::new(new_stream) {
                Ok(s_stream) => {
                    // Add to master list
                    let socket = Socket::new(s_stream);

                    // TODO - Replace with recoverable version once into_inner() is stable
                    // Unfortunately, this is the only stable way to use mutexes at the moment
                    // Hopefully recovering from poisoning will be in 1.2
                    // let mut s_guard = match sockets.lock() {
                    //     Ok(guard) => guard,
                    //     Err(poisoned) => poisoned.into_inner()
                    // };
                    let mut s_guard = sockets.lock().unwrap();
                    let s_list = s_guard.deref_mut();
                    let s_fd = socket.raw_fd();
                    s_list.push_back(socket);

                    // Add to epoll
                    let event = Box::new(EpollEvent {
                        data: s_fd as u64,
                        events: (event_type::EPOLLIN | event_type::EPOLLET)
                        });
                    match epoll::ctl(epoll_instance, ctl_op::ADD, s_fd, event) {
                        Ok(()) => println!("New socket added to epoll list"),
                        Err(e) => println!("Epoll CtrlError: {}", e)
                    };
                }
                Err(e) => {
                    // TODO - write error to log file
                    println!("Error: {}", e);
                }
            };
        }

        // If we get here, shit is real bad. It means we have lost our
        // channel to the outside world.
        // Kill off event loop, so unwinding can begin
        println!("Rust.EventLoop.start - thread finished");
        let _ = err_tx.send(());
    }

    /// Calls epoll_wait forever waiting for events to be fired up from kernel
    fn epoll_loop(uspace_tx: Sender<EventTuple>,
                  sockets: SocketList,
                  epoll_instance: RawFd,
                  err_rx: Receiver<()>) {

        // This is the maximum number of events we want to be notified of at one time
        let mut events = Vec::<EpollEvent>::with_capacity(100);
        unsafe { events.set_len(100); }

        loop {
            // Wait for epoll events
            match epoll::wait(epoll_instance, &mut events[..], -1) {
                Ok(num_events) => {
                    println!("{} epoll event(s) received", num_events);
                    for x in 0..num_events {
                        let tx_clone = uspace_tx.clone();
                        let s_clone = sockets.clone();
                        EventLoop::handle_epoll_event(tx_clone, &events[x as usize], s_clone);
                    }
                }
                Err(e) => {
                    panic!("Error on epoll::wait(): {}", e)
                }
            }

            // If we receive anything on this end or lose communication, we need to halt,
            // because we have no where to send up events, our "user space" channel is
            // gone
            match err_rx.try_recv() {
                Ok(_) => {
                    println!("Error, terminating epoll_loop");
                    break;
                }
                Err(e) => {
                    match e {
                        TryRecvError::Empty => {}
                        _ => {
                            println!("Error, terminating epoll_loo");
                            break;
                        }
                    }
                }
            }
        }
        println!("Rust.EventLoop.epoll_loop - thread finished");
    }

    /// Processes a read on the socket that is ready for reading
    ///
    /// An epoll event is passed to this function, with the fd that is ready to be read
    /// A traversal through the list of sockets is then performed in order to locate the
    /// NbetStream instance that is wrapping that file descriptor.
    /// After a read is performed on that socket, it's data will be passed back to the
    /// "user-space" section of the Server to process the payload however it needs to.
    ///
    /// TODO - Create a faster way to gain a safe reference to the NbetStream wrapping
    /// the fd instead of an O(n) lookup for every event. Currently lookup time is
    /// O(n) * MAX_EPOLL_EVENTS, where MAX_EPOLL_EVENTS is user defined in this function's
    /// caller.
    fn handle_epoll_event(uspace_tx: Sender<EventTuple>,
                          event: &EpollEvent,
                          sockets: SocketList) {

        println!("Rust.EventLoop.handle_epoll_event");

        // The fd we are traversing the list for
        let fd = event.data;

        // We need a handle before the list gets locked and used
        let s_list_clone = sockets.clone();

        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();
        for socket in s_list.iter_mut() {
            if socket.raw_fd() as u64 == fd {
                // We've found the socket for the event passed from epoll
                // Lets attempt to read from it
                match socket.read() {
                    Ok(()) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Ok()");
                        for msg in socket.buffer().iter() {
                            let msg_for_debug = msg.clone();
                            match String::from_utf8() {
                                Ok(msg_str) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string: {}", msg_str);
                                }
                                Err(e) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string.Err: {}", e);
                                }
                            };

                            let list_handle = s_list_clone.clone();
                            let socket_clone = socket.clone();
                            let msg_clone = msg.clone();
                            let _ = uspace_tx.send((list_handle, socket_clone, msg_clone));
                        }
                    }
                    Err(e) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Err(e): {}", e);
                    }
                }
            }
        }
    }
}
<commit_msg>Debugging statements<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::thread;
use std::thread::JoinHandle;
use std::net::TcpStream;
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError
};

use super::types::*;
use super::epoll;
use super::epoll::util::*;
use super::epoll::EpollEvent;
use super::socket::Socket;
use super::simple_stream::nbetstream::NbetStream;

#[allow(dead_code)]
pub struct EventLoop {
    /// Handle to event loop process
    prox: JoinHandle<()>,
    /// Sender<T> to proc
    prox_tx: Sender<TcpStream>
}

impl EventLoop {

    /// Returns a new EventLoop
    pub fn new(server_tx: Sender<EventTuple>) -> EventLoop {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();
        let prox = thread::Builder::new()
            .name("EventLoop".to_string())
            .spawn(move || {
                EventLoop::start(rx, server_tx);
            }).unwrap();

        EventLoop {
            prox: prox,
            prox_tx: tx
        }
    }

    /// Returns a clone of this EventLoop's Sender<TcpStream> channel
    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    /// Main event loop
    fn start(rx: Receiver<TcpStream>, uspace_tx: Sender<EventTuple>) {
        // Master socket list
        let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

        // Our error handler for this thread and it's children
        let (err_tx, err_rx): (Sender<()>, Receiver<()>) = channel();

        // Create an epoll instance
        let result = epoll::create1(0);
        if result.is_err() {
            let err = result.unwrap_err();
            panic!("Unable to create epoll instance: {}", err)
        }
        let epoll_instance = result.unwrap();

        // Start the epoll thread
        let c_sockets = sockets.clone();
        let c_epoll_instance = epoll_instance.clone();
        let epoll_prox = thread::Builder::new()
            .name("EpollLoop".to_string())
            .spawn(move || {
                EventLoop::epoll_loop(uspace_tx, c_sockets, c_epoll_instance, err_rx);
            }).unwrap();

        for new_stream in rx.iter() {
            match NbetStream::new(new_stream) {
                Ok(s_stream) => {
                    // Add to master list
                    let socket = Socket::new(s_stream);

                    // TODO - Replace with recoverable version once into_inner() is stable
                    // Unfortunately, this is the only stable way to use mutexes at the moment
                    // Hopefully recovering from poisoning will be in 1.2
                    // let mut s_guard = match sockets.lock() {
                    //     Ok(guard) => guard,
                    //     Err(poisoned) => poisoned.into_inner()
                    // };
                    let mut s_guard = sockets.lock().unwrap();
                    let s_list = s_guard.deref_mut();
                    let s_fd = socket.raw_fd();
                    s_list.push_back(socket);

                    // Add to epoll
                    let event = Box::new(EpollEvent {
                        data: s_fd as u64,
                        events: (event_type::EPOLLIN | event_type::EPOLLET)
                        });
                    match epoll::ctl(epoll_instance, ctl_op::ADD, s_fd, event) {
                        Ok(()) => println!("New socket added to epoll list"),
                        Err(e) => println!("Epoll CtrlError: {}", e)
                    };
                }
                Err(e) => {
                    // TODO - write error to log file
                    println!("Error: {}", e);
                }
            };
        }

        // If we get here, shit is real bad. It means we have lost our
        // channel to the outside world.
        // Kill off event loop, so unwinding can begin
        println!("Rust.EventLoop.start - thread finished");
        let _ = err_tx.send(());
    }

    /// Calls epoll_wait forever waiting for events to be fired up from kernel
    fn epoll_loop(uspace_tx: Sender<EventTuple>,
                  sockets: SocketList,
                  epoll_instance: RawFd,
                  err_rx: Receiver<()>) {

        // This is the maximum number of events we want to be notified of at one time
        let mut events = Vec::<EpollEvent>::with_capacity(100);
        unsafe { events.set_len(100); }

        loop {
            // Wait for epoll events
            match epoll::wait(epoll_instance, &mut events[..], -1) {
                Ok(num_events) => {
                    println!("{} epoll event(s) received", num_events);
                    for x in 0..num_events {
                        let tx_clone = uspace_tx.clone();
                        let s_clone = sockets.clone();
                        EventLoop::handle_epoll_event(tx_clone, &events[x as usize], s_clone);
                    }
                }
                Err(e) => {
                    panic!("Error on epoll::wait(): {}", e)
                }
            }

            // If we receive anything on this end or lose communication, we need to halt,
            // because we have no where to send up events, our "user space" channel is
            // gone
            match err_rx.try_recv() {
                Ok(_) => {
                    println!("Error, terminating epoll_loop");
                    break;
                }
                Err(e) => {
                    match e {
                        TryRecvError::Empty => {}
                        _ => {
                            println!("Error, terminating epoll_loo");
                            break;
                        }
                    }
                }
            }
        }
        println!("Rust.EventLoop.epoll_loop - thread finished");
    }

    /// Processes a read on the socket that is ready for reading
    ///
    /// An epoll event is passed to this function, with the fd that is ready to be read
    /// A traversal through the list of sockets is then performed in order to locate the
    /// NbetStream instance that is wrapping that file descriptor.
    /// After a read is performed on that socket, it's data will be passed back to the
    /// "user-space" section of the Server to process the payload however it needs to.
    ///
    /// TODO - Create a faster way to gain a safe reference to the NbetStream wrapping
    /// the fd instead of an O(n) lookup for every event. Currently lookup time is
    /// O(n) * MAX_EPOLL_EVENTS, where MAX_EPOLL_EVENTS is user defined in this function's
    /// caller.
    fn handle_epoll_event(uspace_tx: Sender<EventTuple>,
                          event: &EpollEvent,
                          sockets: SocketList) {

        println!("Rust.EventLoop.handle_epoll_event");

        // The fd we are traversing the list for
        let fd = event.data;

        // We need a handle before the list gets locked and used
        let s_list_clone = sockets.clone();

        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();
        for socket in s_list.iter_mut() {
            if socket.raw_fd() as u64 == fd {
                // We've found the socket for the event passed from epoll
                // Lets attempt to read from it
                match socket.read() {
                    Ok(()) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Ok()");
                        for msg in socket.buffer().iter() {
                            let msg_for_debug = msg.clone();
                            match String::from_utf8(msg_for_debug) {
                                Ok(msg_str) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string: {}", msg_str);
                                }
                                Err(e) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string.Err: {}", e);
                                }
                            };

                            let list_handle = s_list_clone.clone();
                            let socket_clone = socket.clone();
                            let msg_clone = msg.clone();
                            let _ = uspace_tx.send((list_handle, socket_clone, msg_clone));
                        }
                    }
                    Err(e) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Err(e): {}", e);
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Dynamically typed value.

use capability::FromClientHook;
use private::capability::{ClientHook, PipelineHook, PipelineOp};
use private::layout::{PointerReader, PointerBuilder};
use traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};
use Result;

#[derive(Copy, Clone)]
pub struct Owned(());

impl <'a> ::traits::Owned<'a> for Owned {
    type Reader = Reader<'a>;
    type Builder = Builder<'a>;
}

impl ::traits::Pipelined for Owned {
    type Pipeline = Pipeline;
}

#[derive(Copy, Clone)]
pub struct Reader<'a> {
    reader: PointerReader<'a>
}

impl <'a> Reader<'a> {
    #[inline]
    pub fn new<'b>(reader: PointerReader<'b>) -> Reader<'b> {
        Reader { reader: reader }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.reader.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<::MessageSize> {
        self.reader.total_size()
    }

    #[deprecated(since = "0.8.7", note = "use target_size() instead")]
    pub fn total_size(&self) -> Result<::MessageSize> {
        self.reader.total_size()
    }

    #[inline]
    pub fn get_as<T: FromPointerReader<'a>>(&self) -> Result<T> {
        FromPointerReader::get_from_pointer(&self.reader)
    }

    pub fn get_as_capability<T: FromClientHook>(&self) -> Result<T> {
        Ok(FromClientHook::new(try!(self.reader.get_capability())))
    }

    //# Used by RPC system to implement pipelining. Applications
    //# generally shouldn't use this directly.
    pub fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Result<Box<ClientHook>> {
        let mut pointer = self.reader;

        for op in ops.iter() {
            match op {
                &PipelineOp::Noop =>  { }
                &PipelineOp::GetPointerField(idx) => {
                    pointer = try!(pointer.get_struct(::std::ptr::null())).get_pointer_field(idx as usize);
                }
            }
        }

        pointer.get_capability()
    }
}

impl <'a> FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>) -> Result<Reader<'a>> {
        Ok(Reader { reader: *reader })
    }
}

impl <'a> ::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
    fn set_pointer_builder<'b>(mut pointer: ::private::layout::PointerBuilder<'b>,
                               value: Reader<'a>) -> Result<()> {
        pointer.copy_from(value.reader, false)
    }

    fn set_pointer_canonical<'b>(mut pointer: PointerBuilder<'b>, value: Reader<'a>) -> Result<()> {
        pointer.copy_from(value.reader, true)
    }
}

impl <'a> ::traits::Imbue<'a> for Reader<'a> {
    fn imbue(&mut self, cap_table: &'a ::private::layout::CapTable) {
        self.reader.imbue(::private::layout::CapTableReader::Plain(cap_table));
    }
}

pub struct Builder<'a> {
    builder: PointerBuilder<'a>
}

impl <'a> Builder<'a> {
    #[inline]
    pub fn new<'b>(builder: PointerBuilder<'a>) -> Builder<'a> {
        Builder { builder: builder }
    }

    pub fn borrow<'b>(&'b mut self) -> Builder<'b> {
        Builder { builder: self.builder.borrow() }
    }

    pub fn is_null(&self) -> bool {
        self.builder.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn total_size(&self) -> Result<::MessageSize> {
        self.builder.as_reader().total_size()
    }

    pub fn get_as<T : FromPointerBuilder<'a>>(self) -> Result<T> {
        FromPointerBuilder::get_from_pointer(self.builder)
    }

    pub fn init_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::init_pointer(self.builder, 0)
    }

    pub fn initn_as<T: FromPointerBuilder<'a>>(self, size: u32) -> T {
        FromPointerBuilder::init_pointer(self.builder, size)
    }

    pub fn set_as<To, From : SetPointerBuilder<To>>(self, value: From) -> Result<()> {
        SetPointerBuilder::<To>::set_pointer_builder(self.builder, value)
    }

    // XXX value should be a user client.
    pub fn set_as_capability(&mut self, value: Box<ClientHook>) {
        self.builder.set_capability(value);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.builder.clear()
    }

    #[inline]
    pub fn as_reader(self) -> Reader<'a> {
        Reader { reader: self.builder.as_reader() }
    }
}

impl <'a> FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(mut builder: PointerBuilder<'a>, _len: u32) -> Builder<'a> {
        if !builder.is_null() {
            builder.clear();
        }
        Builder { builder: builder }
    }
    fn get_from_pointer(builder: PointerBuilder<'a>) -> Result<Builder<'a>> {
        Ok(Builder { builder: builder })
    }
}

impl <'a> ::traits::ImbueMut<'a> for Builder<'a> {
    fn imbue_mut(&mut self, cap_table: &'a mut ::private::layout::CapTable) {
        self.builder.imbue(::private::layout::CapTableBuilder::Plain(cap_table));
    }
}

pub struct Pipeline {
    // XXX this should not be public
    pub hook: Box<PipelineHook>,

    ops: Vec<PipelineOp>,
}

impl Pipeline {
    pub fn new(hook: Box<PipelineHook>) -> Pipeline {
        Pipeline { hook: hook, ops: Vec::new() }
    }

    pub fn noop(&self) -> Pipeline {
        Pipeline { hook: self.hook.add_ref(), ops: self.ops.clone() }
    }

    pub fn get_pointer_field(&self, pointer_index: u16) -> Pipeline {
        let mut new_ops = Vec::with_capacity(self.ops.len() + 1);
        for &op in self.ops.iter() {
            new_ops.push(op)
        }
        new_ops.push(PipelineOp::GetPointerField(pointer_index));
        Pipeline { hook : self.hook.add_ref(), ops: new_ops }
    }

    pub fn as_cap(&self) -> Box<ClientHook> {
        self.hook.get_pipelined_cap(&self.ops)
    }
}

impl ::capability::FromTypelessPipeline for Pipeline {
    fn new(typeless: Pipeline) -> Pipeline {
        typeless
    }
}

#[test]
fn init_clears_value() {
    let mut message = ::message::Builder::new_default();
    {
        let root: ::any_pointer::Builder = message.init_root();
        let mut list: ::primitive_list::Builder<u16> = root.initn_as(10);
        for idx in 0..10 {
            list.set(idx, idx as u16);
        }
    }

    {
        let root: ::any_pointer::Builder = message.init_root();
        assert!(root.is_null());
    }

    let mut output: Vec<u8> = Vec::new();
    ::serialize::write_message(&mut output, &mut message).unwrap();
    assert_eq!(output.len(), 40);
    for byte in &output[8..] {
        // Everything not in the message header is zero.
        assert_eq!(*byte, 0u8);
    }
}
<commit_msg>deprecate any_pointer::Builder::total_size() in favor of target_size()<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Dynamically typed value.

use capability::FromClientHook;
use private::capability::{ClientHook, PipelineHook, PipelineOp};
use private::layout::{PointerReader, PointerBuilder};
use traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};
use Result;

#[derive(Copy, Clone)]
pub struct Owned(());

impl <'a> ::traits::Owned<'a> for Owned {
    type Reader = Reader<'a>;
    type Builder = Builder<'a>;
}

impl ::traits::Pipelined for Owned {
    type Pipeline = Pipeline;
}

#[derive(Copy, Clone)]
pub struct Reader<'a> {
    reader: PointerReader<'a>
}

impl <'a> Reader<'a> {
    #[inline]
    pub fn new<'b>(reader: PointerReader<'b>) -> Reader<'b> {
        Reader { reader: reader }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.reader.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<::MessageSize> {
        self.reader.total_size()
    }

    #[deprecated(since = "0.8.7", note = "use target_size() instead")]
    pub fn total_size(&self) -> Result<::MessageSize> {
        self.reader.total_size()
    }

    #[inline]
    pub fn get_as<T: FromPointerReader<'a>>(&self) -> Result<T> {
        FromPointerReader::get_from_pointer(&self.reader)
    }

    pub fn get_as_capability<T: FromClientHook>(&self) -> Result<T> {
        Ok(FromClientHook::new(try!(self.reader.get_capability())))
    }

    //# Used by RPC system to implement pipelining. Applications
    //# generally shouldn't use this directly.
    pub fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Result<Box<ClientHook>> {
        let mut pointer = self.reader;

        for op in ops.iter() {
            match op {
                &PipelineOp::Noop =>  { }
                &PipelineOp::GetPointerField(idx) => {
                    pointer = try!(pointer.get_struct(::std::ptr::null())).get_pointer_field(idx as usize);
                }
            }
        }

        pointer.get_capability()
    }
}

impl <'a> FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>) -> Result<Reader<'a>> {
        Ok(Reader { reader: *reader })
    }
}

impl <'a> ::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
    fn set_pointer_builder<'b>(mut pointer: ::private::layout::PointerBuilder<'b>,
                               value: Reader<'a>) -> Result<()> {
        pointer.copy_from(value.reader, false)
    }

    fn set_pointer_canonical<'b>(mut pointer: PointerBuilder<'b>, value: Reader<'a>) -> Result<()> {
        pointer.copy_from(value.reader, true)
    }
}

impl <'a> ::traits::Imbue<'a> for Reader<'a> {
    fn imbue(&mut self, cap_table: &'a ::private::layout::CapTable) {
        self.reader.imbue(::private::layout::CapTableReader::Plain(cap_table));
    }
}

pub struct Builder<'a> {
    builder: PointerBuilder<'a>
}

impl <'a> Builder<'a> {
    #[inline]
    pub fn new<'b>(builder: PointerBuilder<'a>) -> Builder<'a> {
        Builder { builder: builder }
    }

    pub fn borrow<'b>(&'b mut self) -> Builder<'b> {
        Builder { builder: self.builder.borrow() }
    }

    pub fn is_null(&self) -> bool {
        self.builder.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<::MessageSize> {
        self.builder.as_reader().total_size()
    }

    #[deprecated(since = "0.8.10", note = "use target_size() instead")]
    pub fn total_size(&self) -> Result<::MessageSize> {
        self.builder.as_reader().total_size()
    }

    pub fn get_as<T : FromPointerBuilder<'a>>(self) -> Result<T> {
        FromPointerBuilder::get_from_pointer(self.builder)
    }

    pub fn init_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::init_pointer(self.builder, 0)
    }

    pub fn initn_as<T: FromPointerBuilder<'a>>(self, size: u32) -> T {
        FromPointerBuilder::init_pointer(self.builder, size)
    }

    pub fn set_as<To, From : SetPointerBuilder<To>>(self, value: From) -> Result<()> {
        SetPointerBuilder::<To>::set_pointer_builder(self.builder, value)
    }

    // XXX value should be a user client.
    pub fn set_as_capability(&mut self, value: Box<ClientHook>) {
        self.builder.set_capability(value);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.builder.clear()
    }

    #[inline]
    pub fn as_reader(self) -> Reader<'a> {
        Reader { reader: self.builder.as_reader() }
    }
}

impl <'a> FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(mut builder: PointerBuilder<'a>, _len: u32) -> Builder<'a> {
        if !builder.is_null() {
            builder.clear();
        }
        Builder { builder: builder }
    }
    fn get_from_pointer(builder: PointerBuilder<'a>) -> Result<Builder<'a>> {
        Ok(Builder { builder: builder })
    }
}

impl <'a> ::traits::ImbueMut<'a> for Builder<'a> {
    fn imbue_mut(&mut self, cap_table: &'a mut ::private::layout::CapTable) {
        self.builder.imbue(::private::layout::CapTableBuilder::Plain(cap_table));
    }
}

pub struct Pipeline {
    // XXX this should not be public
    pub hook: Box<PipelineHook>,

    ops: Vec<PipelineOp>,
}

impl Pipeline {
    pub fn new(hook: Box<PipelineHook>) -> Pipeline {
        Pipeline { hook: hook, ops: Vec::new() }
    }

    pub fn noop(&self) -> Pipeline {
        Pipeline { hook: self.hook.add_ref(), ops: self.ops.clone() }
    }

    pub fn get_pointer_field(&self, pointer_index: u16) -> Pipeline {
        let mut new_ops = Vec::with_capacity(self.ops.len() + 1);
        for &op in self.ops.iter() {
            new_ops.push(op)
        }
        new_ops.push(PipelineOp::GetPointerField(pointer_index));
        Pipeline { hook : self.hook.add_ref(), ops: new_ops }
    }

    pub fn as_cap(&self) -> Box<ClientHook> {
        self.hook.get_pipelined_cap(&self.ops)
    }
}

impl ::capability::FromTypelessPipeline for Pipeline {
    fn new(typeless: Pipeline) -> Pipeline {
        typeless
    }
}

#[test]
fn init_clears_value() {
    let mut message = ::message::Builder::new_default();
    {
        let root: ::any_pointer::Builder = message.init_root();
        let mut list: ::primitive_list::Builder<u16> = root.initn_as(10);
        for idx in 0..10 {
            list.set(idx, idx as u16);
        }
    }

    {
        let root: ::any_pointer::Builder = message.init_root();
        assert!(root.is_null());
    }

    let mut output: Vec<u8> = Vec::new();
    ::serialize::write_message(&mut output, &mut message).unwrap();
    assert_eq!(output.len(), 40);
    for byte in &output[8..] {
        // Everything not in the message header is zero.
        assert_eq!(*byte, 0u8);
    }
}
<|endoftext|>


<commit_before>#![warn(clippy::all)]
#![allow(unused_variables)]
#![allow(unused_assignments)]
#![allow(clippy::if_same_then_else)]
#![allow(clippy::deref_addrof)]

fn foo() -> bool {
    true
}

#[rustfmt::skip]
fn main() {
    // weird `else` formatting:
    if foo() {
    } {
    }

    if foo() {
    } if foo() {
    }

    let _ = { // if as the last expression
        let _ = 0;

        if foo() {
        } if foo() {
        }
        else {
        }
    };

    let _ = { // if in the middle of a block
        if foo() {
        } if foo() {
        }
        else {
        }

        let _ = 0;
    };

    if foo() {
    } else
    {
    }

    if foo() {
    }
    else
    {
    }

    if foo() {
    } else
    if foo() { // the span of the above error should continue here
    }

    if foo() {
    }
    else
    if foo() { // the span of the above error should continue here
    }

    // those are ok:
    if foo() {
    }
    {
    }

    if foo() {
    } else {
    }

    if foo() {
    }
    else {
    }

    if foo() {
    }
    if foo() {
    }

    if foo() {
    } else if foo() {
    }

    if foo() {
    }
    else if foo() {
    }

    if foo() {
    }
    else if
    foo() {}

    // weird op_eq formatting:
    let mut a = 42;
    a =- 35;
    a =* &191;

    let mut b = true;
    b =! false;

    // those are ok:
    a = -35;
    a = *&191;
    b = !false;

    // possible missing comma in an array
    let _ = &[
        -1, -2, -3 // <= no comma here
        -4, -5, -6
    ];
    let _ = &[
        -1, -2, -3 // <= no comma here
        *4, -5, -6
    ];

    // those are ok:
    let _ = &[
        -1, -2, -3,
        -4, -5, -6
    ];
    let _ = &[
        -1, -2, -3,
        -4, -5, -6,
    ];
    let _ = &[
        1 + 2, 3 +
        4, 5 + 6,
    ];

    // don't lint for bin op without unary equiv
    // issue 3244
    vec![
        1
        / 2,
    ];
    // issue 3396
    vec![
        true
        | false,
    ];

    // don't lint if the indentation suggests not to
    let _ = &[
        1 + 2, 3
                - 4, 5
    ];
    // lint if it doesnt
    let _ = &[
        -1
        -4,
    ];
}
<commit_msg>fix typos<commit_after>#![warn(clippy::all)]
#![allow(unused_variables)]
#![allow(unused_assignments)]
#![allow(clippy::if_same_then_else)]
#![allow(clippy::deref_addrof)]

fn foo() -> bool {
    true
}

#[rustfmt::skip]
fn main() {
    // weird `else` formatting:
    if foo() {
    } {
    }

    if foo() {
    } if foo() {
    }

    let _ = { // if as the last expression
        let _ = 0;

        if foo() {
        } if foo() {
        }
        else {
        }
    };

    let _ = { // if in the middle of a block
        if foo() {
        } if foo() {
        }
        else {
        }

        let _ = 0;
    };

    if foo() {
    } else
    {
    }

    if foo() {
    }
    else
    {
    }

    if foo() {
    } else
    if foo() { // the span of the above error should continue here
    }

    if foo() {
    }
    else
    if foo() { // the span of the above error should continue here
    }

    // those are ok:
    if foo() {
    }
    {
    }

    if foo() {
    } else {
    }

    if foo() {
    }
    else {
    }

    if foo() {
    }
    if foo() {
    }

    if foo() {
    } else if foo() {
    }

    if foo() {
    }
    else if foo() {
    }

    if foo() {
    }
    else if
    foo() {}

    // weird op_eq formatting:
    let mut a = 42;
    a =- 35;
    a =* &191;

    let mut b = true;
    b =! false;

    // those are ok:
    a = -35;
    a = *&191;
    b = !false;

    // possible missing comma in an array
    let _ = &[
        -1, -2, -3 // <= no comma here
        -4, -5, -6
    ];
    let _ = &[
        -1, -2, -3 // <= no comma here
        *4, -5, -6
    ];

    // those are ok:
    let _ = &[
        -1, -2, -3,
        -4, -5, -6
    ];
    let _ = &[
        -1, -2, -3,
        -4, -5, -6,
    ];
    let _ = &[
        1 + 2, 3 +
        4, 5 + 6,
    ];

    // don't lint for bin op without unary equiv
    // issue 3244
    vec![
        1
        / 2,
    ];
    // issue 3396
    vec![
        true
        | false,
    ];

    // don't lint if the indentation suggests not to
    let _ = &[
        1 + 2, 3
                - 4, 5
    ];
    // lint if it doesn't
    let _ = &[
        -1
        -4,
    ];
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_target;

use rustc_data_structures::profiling::print_time_passes_entry;
use rustc_interface::interface;
use rustc_session::config::ErrorOutputType;
use rustc_session::early_error;
use rustc_target::spec::PanicStrategy;

#[derive(Default)]
pub struct CraneliftPassesCallbacks {
    time_passes: bool,
}

impl rustc_driver::Callbacks for CraneliftPassesCallbacks {
    fn config(&mut self, config: &mut interface::Config) {
        // If a --prints=... option has been given, we don't print the "total"
        // time because it will mess up the --prints output. See #64339.
        self.time_passes = config.opts.prints.is_empty()
            && (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time);

        config.opts.cg.panic = Some(PanicStrategy::Abort);
        config.opts.debugging_opts.panic_abort_tests = true;
        config.opts.maybe_sysroot = Some(
            config.opts.maybe_sysroot.clone().unwrap_or(
                std::env::current_exe()
                    .unwrap()
                    .parent()
                    .unwrap()
                    .join("sysroot"),
            ),
        );
    }
}

fn main() {
    let start = std::time::Instant::now();
    rustc_driver::init_rustc_env_logger();
    let mut callbacks = CraneliftPassesCallbacks::default();
    rustc_driver::install_ice_hook();
    let exit_code = rustc_driver::catch_with_exit_code(|| {
        let mut use_jit = false;

        let mut args = std::env::args_os()
            .enumerate()
            .map(|(i, arg)| {
                arg.into_string().unwrap_or_else(|arg| {
                    early_error(
                        ErrorOutputType::default(),
                        &format!("Argument {} is not valid Unicode: {:?}", i, arg),
                    )
                })
            })
            .filter(|arg| {
                if arg == "--jit" {
                    use_jit = true;
                    false
                } else {
                    true
                }
            })
            .collect::<Vec<_>>();
        if use_jit {
            args.push("-Cprefer-dynamic".to_string());
        }
        let mut run_compiler = rustc_driver::RunCompiler::new(&args, &mut callbacks);
        run_compiler.set_make_codegen_backend(Some(Box::new(move |_| {
            Box::new(rustc_codegen_cranelift::CraneliftCodegenBackend {
                config: rustc_codegen_cranelift::BackendConfig { use_jit },
            })
        })));
        run_compiler.run()
    });
    // The extra `\t` is necessary to align this label with the others.
    print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed());
    std::process::exit(exit_code)
}
<commit_msg>Changed unwrap_or to unwrap_or_else in some places.<commit_after>#![feature(rustc_private)]

extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_target;

use rustc_data_structures::profiling::print_time_passes_entry;
use rustc_interface::interface;
use rustc_session::config::ErrorOutputType;
use rustc_session::early_error;
use rustc_target::spec::PanicStrategy;

#[derive(Default)]
pub struct CraneliftPassesCallbacks {
    time_passes: bool,
}

impl rustc_driver::Callbacks for CraneliftPassesCallbacks {
    fn config(&mut self, config: &mut interface::Config) {
        // If a --prints=... option has been given, we don't print the "total"
        // time because it will mess up the --prints output. See #64339.
        self.time_passes = config.opts.prints.is_empty()
            && (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time);

        config.opts.cg.panic = Some(PanicStrategy::Abort);
        config.opts.debugging_opts.panic_abort_tests = true;
        config.opts.maybe_sysroot = Some(
            config.opts.maybe_sysroot.clone().unwrap_or_else(
                || std::env::current_exe()
                    .unwrap()
                    .parent()
                    .unwrap()
                    .join("sysroot"),
            ),
        );
    }
}

fn main() {
    let start = std::time::Instant::now();
    rustc_driver::init_rustc_env_logger();
    let mut callbacks = CraneliftPassesCallbacks::default();
    rustc_driver::install_ice_hook();
    let exit_code = rustc_driver::catch_with_exit_code(|| {
        let mut use_jit = false;

        let mut args = std::env::args_os()
            .enumerate()
            .map(|(i, arg)| {
                arg.into_string().unwrap_or_else(|arg| {
                    early_error(
                        ErrorOutputType::default(),
                        &format!("Argument {} is not valid Unicode: {:?}", i, arg),
                    )
                })
            })
            .filter(|arg| {
                if arg == "--jit" {
                    use_jit = true;
                    false
                } else {
                    true
                }
            })
            .collect::<Vec<_>>();
        if use_jit {
            args.push("-Cprefer-dynamic".to_string());
        }
        let mut run_compiler = rustc_driver::RunCompiler::new(&args, &mut callbacks);
        run_compiler.set_make_codegen_backend(Some(Box::new(move |_| {
            Box::new(rustc_codegen_cranelift::CraneliftCodegenBackend {
                config: rustc_codegen_cranelift::BackendConfig { use_jit },
            })
        })));
        run_compiler.run()
    });
    // The extra `\t` is necessary to align this label with the others.
    print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed());
    std::process::exit(exit_code)
}
<|endoftext|>