<commit_before>use std::io::{Error, ErrorKind, Read, 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::proto::RawMessage;
use birch::socket::{IrcSocketConfig, IrcWriter};

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

const MAX_LINE_LENGTH: usize = 1024;

struct Socket {
    // Spec says 512 "chars". Does this mean ASCII? Add in some
    // padding anyway
    //
    // Second element contains current length of the buffer.
    line_buf: ([u8; MAX_LINE_LENGTH], usize),
    stream: TcpStream,
}

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

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

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

impl Socket {
    fn from_stream(stream: TcpStream) -> Result<Self> {
        Ok(Self {
            line_buf: ([0u8; MAX_LINE_LENGTH], 0),
            stream,
        })
    }

    // TODO:  This is super fragile. Need tests
    fn read_message(&mut self) -> Result<Option<RawMessage>> {
        let (ref mut buf, len) = self.line_buf;

        if let Some(nl) = buf.iter().position(|&c| c == b'\n') {
            let msg = std::str::from_utf8(&buf[..nl])
                .map(|line| line.trim_end_matches(|c| c == '\r' || c == '\n'))
                .map_err(|_| Error::new(ErrorKind::Other, "invalid UTF-8"))
                .and_then(|line| {
                    RawMessage::parse(line).map(Some).ok_or_else(|| {
                        Error::new(ErrorKind::Other, "failed to parse message")
                    })
                });

            // "Rotate" the buffer left and clear everything.
            let end = nl + 1;
            buf[..end].iter_mut().for_each(|b| *b = 0);
            buf.rotate_left(end);
            self.line_buf.1 -= end;

            return msg;
        } else if len >= MAX_LINE_LENGTH {
            // Reached max length without seeing a newline
            return Err(Error::new(ErrorKind::Other, "max line length exceeded!"));
        }

        // No messages to be parsed yet, fill the buffer.
        self.line_buf.1 += self.stream.read(&mut buf[len..])?;
        Ok(None)
    }
}

impl std::io::Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.stream.write(buf)
    }

    fn flush(&mut self) -> Result<()> {
        self.stream.flush()
    }
}

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 new(stream: TcpStream) -> Self {
        let socket = Socket::from_stream(stream).expect("create client socket");
        let conn = ClientConnection::new();

        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 {
    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 {
            sockets: Slab::with_capacity(1024),
            clients: Slab::with_capacity(32),
            networks: Slab::with_capacity(16),
        }
    }

    fn accept_client(&mut self, poll: &Poll, socket: TcpStream) -> Result<()> {
        let client_id = self.clients.insert(Client::new(socket));
        let token = self.sockets.insert(SocketKind::Client(client_id));

        poll.register(
            &self.clients.get(client_id).unwrap().socket,
            Token(token),
            Ready::readable(),
            PollOpt::edge(),
        )?;

        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 = match network.socket.read_message()? {
            Some(msg) => msg,
            None => return Ok(()),
        };

        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 = match client.socket.read_message()? {
            Some(msg) => msg,
            None => return Ok(()),
        };

        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, poll: &Poll) -> 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(poll, *client_id)?;
        }

        Ok(())
    }

    // TODO: This is a bit too complicated
    fn remove_client(&mut self, poll: &Poll, id: ClientId) -> Result<()> {
        let client = self.clients.remove(id);
        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, poll: &Poll) -> Result<()> {
        for (id, network) in self.networks.iter_mut().filter(|(_, n)| !n.connected) {
            println!("network {} is disconnected... attempting reconnect", id);
            match network.reconnect() {
                Ok(()) => 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,
        poll: &Poll,
        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(poll)?;
                self.reconnect_networks(poll)?;
            }

            Some(&SocketKind::Listener) => loop {
                match listener.accept() {
                    Ok((socket, _)) => self.accept_client(&poll, 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;
                        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(poll, 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<()> {
        let poll = Poll::new()?;

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

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

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

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

            for ev in events {
                self.handle_poll_event(&poll, &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>Extract logic into MessageBuffer<commit_after>use std::io::{Error, ErrorKind, Read, 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::proto::RawMessage;
use birch::socket::{IrcSocketConfig, IrcWriter};

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

const MAX_LINE_LENGTH: usize = 1024;

struct MessageBuffer {
    buf: [u8; MAX_LINE_LENGTH],
    len: usize,
}

impl MessageBuffer {
    fn new() -> Self {
        Self {
            buf: [0u8; MAX_LINE_LENGTH],
            len: 0,
        }
    }

    // TODO: This logic is complicated. Test this.
    fn extract_message(&mut self, nl_pos: usize) -> Result<RawMessage> {
        let msg = std::str::from_utf8(&self.buf[..nl_pos])
            .map(|line| line.trim_end_matches(|c| c == '\r' || c == '\n'))
            .map_err(|_| Error::new(ErrorKind::Other, "invalid UTF-8"))
            .and_then(|line| {
                RawMessage::parse(line).ok_or_else(|| {
                    Error::new(ErrorKind::Other, "failed to parse message")
                })
            });

        // "Rotate" the buffer left and clear everything.
        let end = nl_pos + 1;
        self.buf[..end].iter_mut().for_each(|b| *b = 0);
        self.buf.rotate_left(end);
        self.len -= end;

        return msg;
    }

    /// Continually fill buffer from `r` until an error occurs or a
    /// message is produced.
    fn read<R: Read>(&mut self, r: &mut R) -> Result<RawMessage> {
        loop {
            if let Some(nl) = self.buf.iter().position(|&c| c == b'\n') {
                return self.extract_message(nl);
            } else if self.len >= MAX_LINE_LENGTH {
                // Reached max length without seeing a newline
                return Err(Error::new(ErrorKind::Other, "max line length exceeded!"));
            }

            // No messages to be parsed yet, fill the buffer.
            self.len += r.read(&mut self.buf[self.len..])?;
        }
    }
}

struct Socket {
    buf: MessageBuffer,
    stream: TcpStream,
}

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

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

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

impl Socket {
    fn from_stream(stream: TcpStream) -> Result<Self> {
        Ok(Self {
            buf: MessageBuffer::new(),
            stream,
        })
    }

    // TODO:  This is super fragile. Need tests
    fn read_message(&mut self) -> Result<RawMessage> {
        self.buf.read(&mut self.stream)
    }
}

impl std::io::Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.stream.write(buf)
    }

    fn flush(&mut self) -> Result<()> {
        self.stream.flush()
    }
}

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 new(stream: TcpStream) -> Self {
        let socket = Socket::from_stream(stream).expect("create client socket");
        let conn = ClientConnection::new();

        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 {
    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 {
            sockets: Slab::with_capacity(1024),
            clients: Slab::with_capacity(32),
            networks: Slab::with_capacity(16),
        }
    }

    fn accept_client(&mut self, poll: &Poll, socket: TcpStream) -> Result<()> {
        let client_id = self.clients.insert(Client::new(socket));
        let token = self.sockets.insert(SocketKind::Client(client_id));

        poll.register(
            &self.clients.get(client_id).unwrap().socket,
            Token(token),
            Ready::readable(),
            PollOpt::edge(),
        )?;

        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, poll: &Poll) -> 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(poll, *client_id)?;
        }

        Ok(())
    }

    // TODO: This is a bit too complicated
    fn remove_client(&mut self, poll: &Poll, id: ClientId) -> Result<()> {
        let client = self.clients.remove(id);
        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, poll: &Poll) -> Result<()> {
        for (id, network) in self.networks.iter_mut().filter(|(_, n)| !n.connected) {
            println!("network {} is disconnected... attempting reconnect", id);
            match network.reconnect() {
                Ok(()) => 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,
        poll: &Poll,
        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(poll)?;
                self.reconnect_networks(poll)?;
            }

            Some(&SocketKind::Listener) => loop {
                match listener.accept() {
                    Ok((socket, _)) => self.accept_client(&poll, 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;
                        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(poll, 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<()> {
        let poll = Poll::new()?;

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

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

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

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

            for ev in events {
                self.handle_poll_event(&poll, &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>pub fn set_or_check<T>(maybe: &mut Option<T>, value: T)
where
    T: std::fmt::Debug + PartialEq
{
    let previous = maybe.replace(value);

    assert!(&previous == maybe, "Expected {:?} and {:?} to be equal", &maybe, &previous);
}
<commit_msg>Handle setting the first value<commit_after>pub fn set_or_check<T>(maybe: &mut Option<T>, value: T)
where
    T: std::fmt::Debug + PartialEq
{
    let previous = maybe.replace(value);
    if previous.is_some() {
        assert!(&previous == maybe, "Expected {:?} and {:?} to be equal", &maybe, &previous);
    }
}
<|endoftext|>


<commit_before>// FIXME: Replace these examples with executable tests
//! Traits related to relationships between multiple tables.
//!
//! **Note: This feature is under active development, and we are seeking feedback on the APIs that
//! have been released. Please feel free to [open issues][open-issue], or join [our chat][gitter]
//! to provide feedback.**
//!
//! [open-issue]: https://github.com/diesel-rs/diesel/issues/new
//! [gitter]: https://gitter.im/diesel-rs/diesel
//!
//! Note: The derives in this guide are provided by `diesel_codegen`. Make sure you have
//! `#[macro_use] extern crate diesel_codegen;` at the root of your crate.
//!
//! Associations in Diesel are bidirectional, but primarily focus on the child-to-parent
//! relationship. You can declare an association between two records with
//! `#[belongs_to]`.
//!
//! ```rust
//! // You need to have the table definitions from `infer_schema!` or `table!` in scope to
//! // derive Identifiable.
//! # #[macro_use] extern crate diesel;
//! # #[macro_use] extern crate diesel_codegen;
//! # include!("src/doctest_setup.rs");
//! use schema::{posts, users};
//!
//! #[derive(Identifiable, Queryable)]
//! pub struct User {
//!     id: i32,
//!     name: String,
//! }
//!
//! # #[derive(Debug, PartialEq)]
//! #[derive(Identifiable, Queryable, Associations)]
//! #[belongs_to(User)]
//! pub struct Post {
//!     id: i32,
//!     user_id: i32,
//!     title: String,
//! }
//!
//! # fn main() {
//! # let connection = establish_connection();
//! # let user = users::table.find(2).get_result::<User>(&connection).unwrap();
//! # let posts = Post::belonging_to(&user).load::<Post>(&connection);
//! # assert_eq!(posts, Ok(vec![Post { id: 3, user_id: 2, title: "My first post too".to_owned() }]));
//! # }
//! ```
//!
//! Note that in addition to the `#[belongs_to]` annotation, we also need to
//! `#[derive(Associations)]`
//!
//! `#[belongs_to]` is given the name of the struct that represents the parent. Both types
//! must implement the [`Identifiable`][identifiable] trait. The struct or table referenced in your
//! association has to be in scope, so you'll need `use schema::posts` or similar to bring the
//! table into scope, and `use some_module::User` if `User` were in a different module.
//!
//! [Identifiable]: trait.Identifiable.html
//!
//! If the name of your foreign key doesn't follow the convention `tablename_id`, you can specify a
//! custom one to `#[belongs_to]` by adding a `foreign_key` argument to the
//! attribute like so `#[belongs_to(Foo, foreign_key="mykey")]`.
//!
//! Once the associations are defined, you can join between the two tables using the
//! [`inner_join`][inner-join] or [`left_outer_join`][left-outer-join].
//!
//! [inner-join]: /diesel/query_source/trait.Table.html#method.inner_join
//! [left-outer-join]: /diesel/query_source/trait.Table.html#method.left_outer_join
//!
//! ```ignore
//! let data: Vec<(User, Post)> = users::table.inner_join(posts::table).load(&connection);
//! ```
//!
//! Note: Due to language limitations, only two tables can be joined per query. This will change in
//! the future.
//!
//! Typically however, queries are loaded in multiple queries. For most datasets, the reduced
//! amount of duplicated information sent over the wire saves more time than the extra round trip
//! costs us. You can load the children for a single parent using the
//! [`belonging_to`][belonging-to]
//!
//! [belonging-to]: /diesel/prelude/trait.BelongingToDsl.html#tymethod.belonging_to
//!
//! ```ignore
//! let user = try!(users::find(1).first(&connection));
//! let posts = Post::belonging_to(&user).load(&connection);
//! ```
//!
//! If you're coming from other ORMs, you'll notice that this design is quite different from most.
//! There you would have an instance method on the parent, or have the children stored somewhere on
//! the posts. This design leads to many problems, including [N+1 query
//! bugs][load-your-entire-database-into-memory-lol], and runtime errors when accessing an
//! association that isn't there.
//!
//! [load-your-entire-database-into-memory-lol]: http://stackoverflow.com/q/97197/1254484
//!
//! In Diesel, data and its associations are considered to be separate. If you want to pass around
//! a user and all of its posts, that type is `(User, Vec<Post>)`.
//!
//! Next lets look at how to load the children for more than one parent record.
//! [`belonging_to`][belonging-to] can be used to load the data, but we'll also need to group it
//! with its parents. For this we use an additional method [`grouped_by`][grouped-by]
//!
//! [grouped-by]: trait.GroupedBy.html#tymethod.grouped_by
//!
//! ```ignore
//! fn first_twenty_users_and_their_posts(conn: &PgConnection) -> QueryResult<Vec<(User, Vec<Post>)>> {
//!     let users = try!(users::limit(20).load::<User>(conn));
//!     let posts = try!(Post::belonging_to(&users).load::<Post>(conn));
//!     let grouped_posts = posts.grouped_by(&users);
//!     users.into_iter().zip(grouped_posts).collect()
//! }
//! ```
//!
//! [`grouped_by`][grouped-by] takes a `Vec<Child>` and a `Vec<Parent>` and returns a
//! `Vec<Vec<Child>>` where the index of the children matches the index of the parent they belong
//! to. Or to put it another way, it returns them in an order ready to be `zip`ed with the parents. You
//! can do this multiple times. For example, if you wanted to load the comments for all the posts
//! as well, you could do this: (explicit type annotations have been added for documentation
//! purposes)
//!
//! ```ignore
//! let posts: Vec<Post> = try!(Post::belonging_to(&users).load());
//! let comments: Vec<Comment> = try!(Comment::belonging_to(&posts).load());
//! let comments: Vec<Vec<Comment>> = comments.grouped_by(&posts);
//! let posts_and_comments: Vec<Vec<(Post, Vec<Comment>)>> = posts.into_iter().zip(comments).grouped_by(&users);
//! let result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = users.into_iter().zip(posts_and_comments).collect();
//! ```
//!
//! And that's it. This module will be expanded in the future with more complex joins, and the
//! ability to define "through" associations (e.g. load all the comments left on any posts written
//! by a user in a single query). However, the goal is to provide simple building blocks which can
//! be used to construct the complex behavior applications need.
mod belongs_to;

use std::hash::Hash;

use query_source::Table;

pub use self::belongs_to::{BelongsTo, GroupedBy};

pub trait HasTable {
    type Table: Table;

    fn table() -> Self::Table;
}

impl<'a, T: HasTable> HasTable for &'a T {
    type Table = T::Table;

    fn table() -> Self::Table {
        T::table()
    }
}

/// Represents a struct which can be identified on a single table in the
/// database. This must be implemented to use associations, and some features of
/// updating. This trait is usually implemented on a reference to a struct, not
/// the struct itself.
///
/// ### Deriving
///
/// This trait can be automatically derived using `diesel_codegen` by adding
/// `#[derive(Identifiable)]` to your struct. The primary key will be assumed to be a field and
/// column called `id`. If it's not, you can annotate your structure with `#[primary_key(your_id)]`
/// or `#[primary_key(your_id, second_id)]`. By default the table will be assumed to be the plural
/// form of the struct name (using *very* dumb pluralization -- it just adds an `s` at the end). If
/// your table name differs from that convention, or requires complex pluralization, it can be
/// specified using `#[table_name = "some_table_name"]`. The inferred table name is considered
/// public API and will never change without a major version bump.
pub trait Identifiable: HasTable {
    type Id: Hash + Eq;

    fn id(self) -> Self::Id;
}
<commit_msg>Remove outdated note in the associations module doc<commit_after>// FIXME: Replace these examples with executable tests
//! Traits related to relationships between multiple tables.
//!
//! **Note: This feature is under active development, and we are seeking feedback on the APIs that
//! have been released. Please feel free to [open issues][open-issue], or join [our chat][gitter]
//! to provide feedback.**
//!
//! [open-issue]: https://github.com/diesel-rs/diesel/issues/new
//! [gitter]: https://gitter.im/diesel-rs/diesel
//!
//! Note: The derives in this guide are provided by `diesel_codegen`. Make sure you have
//! `#[macro_use] extern crate diesel_codegen;` at the root of your crate.
//!
//! Associations in Diesel are bidirectional, but primarily focus on the child-to-parent
//! relationship. You can declare an association between two records with
//! `#[belongs_to]`.
//!
//! ```rust
//! // You need to have the table definitions from `infer_schema!` or `table!` in scope to
//! // derive Identifiable.
//! # #[macro_use] extern crate diesel;
//! # #[macro_use] extern crate diesel_codegen;
//! # include!("src/doctest_setup.rs");
//! use schema::{posts, users};
//!
//! #[derive(Identifiable, Queryable)]
//! pub struct User {
//!     id: i32,
//!     name: String,
//! }
//!
//! # #[derive(Debug, PartialEq)]
//! #[derive(Identifiable, Queryable, Associations)]
//! #[belongs_to(User)]
//! pub struct Post {
//!     id: i32,
//!     user_id: i32,
//!     title: String,
//! }
//!
//! # fn main() {
//! # let connection = establish_connection();
//! # let user = users::table.find(2).get_result::<User>(&connection).unwrap();
//! # let posts = Post::belonging_to(&user).load::<Post>(&connection);
//! # assert_eq!(posts, Ok(vec![Post { id: 3, user_id: 2, title: "My first post too".to_owned() }]));
//! # }
//! ```
//!
//! Note that in addition to the `#[belongs_to]` annotation, we also need to
//! `#[derive(Associations)]`
//!
//! `#[belongs_to]` is given the name of the struct that represents the parent. Both types
//! must implement the [`Identifiable`][identifiable] trait. The struct or table referenced in your
//! association has to be in scope, so you'll need `use schema::posts` or similar to bring the
//! table into scope, and `use some_module::User` if `User` were in a different module.
//!
//! [Identifiable]: trait.Identifiable.html
//!
//! If the name of your foreign key doesn't follow the convention `tablename_id`, you can specify a
//! custom one to `#[belongs_to]` by adding a `foreign_key` argument to the
//! attribute like so `#[belongs_to(Foo, foreign_key="mykey")]`.
//!
//! Once the associations are defined, you can join between the two tables using the
//! [`inner_join`][inner-join] or [`left_outer_join`][left-outer-join].
//!
//! [inner-join]: /diesel/query_source/trait.Table.html#method.inner_join
//! [left-outer-join]: /diesel/query_source/trait.Table.html#method.left_outer_join
//!
//! ```ignore
//! let data: Vec<(User, Post)> = users::table.inner_join(posts::table).load(&connection);
//! ```
//!
//! Typically however, queries are loaded in multiple queries. For most datasets, the reduced
//! amount of duplicated information sent over the wire saves more time than the extra round trip
//! costs us. You can load the children for a single parent using the
//! [`belonging_to`][belonging-to]
//!
//! [belonging-to]: /diesel/prelude/trait.BelongingToDsl.html#tymethod.belonging_to
//!
//! ```ignore
//! let user = try!(users::find(1).first(&connection));
//! let posts = Post::belonging_to(&user).load(&connection);
//! ```
//!
//! If you're coming from other ORMs, you'll notice that this design is quite different from most.
//! There you would have an instance method on the parent, or have the children stored somewhere on
//! the posts. This design leads to many problems, including [N+1 query
//! bugs][load-your-entire-database-into-memory-lol], and runtime errors when accessing an
//! association that isn't there.
//!
//! [load-your-entire-database-into-memory-lol]: http://stackoverflow.com/q/97197/1254484
//!
//! In Diesel, data and its associations are considered to be separate. If you want to pass around
//! a user and all of its posts, that type is `(User, Vec<Post>)`.
//!
//! Next lets look at how to load the children for more than one parent record.
//! [`belonging_to`][belonging-to] can be used to load the data, but we'll also need to group it
//! with its parents. For this we use an additional method [`grouped_by`][grouped-by]
//!
//! [grouped-by]: trait.GroupedBy.html#tymethod.grouped_by
//!
//! ```ignore
//! fn first_twenty_users_and_their_posts(conn: &PgConnection) -> QueryResult<Vec<(User, Vec<Post>)>> {
//!     let users = try!(users::limit(20).load::<User>(conn));
//!     let posts = try!(Post::belonging_to(&users).load::<Post>(conn));
//!     let grouped_posts = posts.grouped_by(&users);
//!     users.into_iter().zip(grouped_posts).collect()
//! }
//! ```
//!
//! [`grouped_by`][grouped-by] takes a `Vec<Child>` and a `Vec<Parent>` and returns a
//! `Vec<Vec<Child>>` where the index of the children matches the index of the parent they belong
//! to. Or to put it another way, it returns them in an order ready to be `zip`ed with the parents. You
//! can do this multiple times. For example, if you wanted to load the comments for all the posts
//! as well, you could do this: (explicit type annotations have been added for documentation
//! purposes)
//!
//! ```ignore
//! let posts: Vec<Post> = try!(Post::belonging_to(&users).load());
//! let comments: Vec<Comment> = try!(Comment::belonging_to(&posts).load());
//! let comments: Vec<Vec<Comment>> = comments.grouped_by(&posts);
//! let posts_and_comments: Vec<Vec<(Post, Vec<Comment>)>> = posts.into_iter().zip(comments).grouped_by(&users);
//! let result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = users.into_iter().zip(posts_and_comments).collect();
//! ```
//!
//! And that's it. This module will be expanded in the future with more complex joins, and the
//! ability to define "through" associations (e.g. load all the comments left on any posts written
//! by a user in a single query). However, the goal is to provide simple building blocks which can
//! be used to construct the complex behavior applications need.
mod belongs_to;

use std::hash::Hash;

use query_source::Table;

pub use self::belongs_to::{BelongsTo, GroupedBy};

pub trait HasTable {
    type Table: Table;

    fn table() -> Self::Table;
}

impl<'a, T: HasTable> HasTable for &'a T {
    type Table = T::Table;

    fn table() -> Self::Table {
        T::table()
    }
}

/// Represents a struct which can be identified on a single table in the
/// database. This must be implemented to use associations, and some features of
/// updating. This trait is usually implemented on a reference to a struct, not
/// the struct itself.
///
/// ### Deriving
///
/// This trait can be automatically derived using `diesel_codegen` by adding
/// `#[derive(Identifiable)]` to your struct. The primary key will be assumed to be a field and
/// column called `id`. If it's not, you can annotate your structure with `#[primary_key(your_id)]`
/// or `#[primary_key(your_id, second_id)]`. By default the table will be assumed to be the plural
/// form of the struct name (using *very* dumb pluralization -- it just adds an `s` at the end). If
/// your table name differs from that convention, or requires complex pluralization, it can be
/// specified using `#[table_name = "some_table_name"]`. The inferred table name is considered
/// public API and will never change without a major version bump.
pub trait Identifiable: HasTable {
    type Id: Hash + Eq;

    fn id(self) -> Self::Id;
}
<|endoftext|>


<commit_before>use typedef::*;
use value::Value;

pub const PREAMBLE: &str = "BAKERVM";

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Target {
    Framebuffer(Address),
    ValueIndex(Address),
    Stack,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Instruction {
    Add(Target, Target),
    Sub(Target, Target),
    Div(Target, Target),
    Mul(Target, Target),
    Rem(Target, Target),

    Cmp(Target, Target),
    Jmp(Address),
    JmpLt(Address),
    JmpGt(Address),
    JmpEq(Address),
    JmpLtEq(Address),
    JmpGtEq(Address),

    Push(Target, Value),
    Mov(Target, Target),
    Swp(Target, Target),

    Call(Address),
    Ret,

    Halt,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DisplayResolution {
    pub width: usize,
    pub height: usize,
}

impl Default for DisplayResolution {
    fn default() -> Self {
        DisplayResolution {
            width: 360,
            height: 200,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct VMConfig {
    pub display_resolution: DisplayResolution,
    pub display_scale: Float,
    pub keyboard_enabled: bool,
    pub mouse_enabled: bool,
}

impl Default for VMConfig {
    fn default() -> Self {
        VMConfig {
            display_resolution: Default::default(),
            display_scale: 4.0,
            keyboard_enabled: true,
            mouse_enabled: true,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Program {
    pub preamble: String,
    pub version: String,
    pub config: VMConfig,
    pub instructions: Vec<Instruction>,
}

impl Default for Program {
    fn default() -> Self {
        Program {
            preamble: String::from(PREAMBLE),
            version: String::from(env!("CARGO_PKG_VERSION")),
            config: Default::default(),
            instructions: Default::default(),
        }
    }
}

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

    #[test]
    fn comparison() {
        assert!(Value::Float(1.3) < Value::Float(1.4));
        assert!(Value::Float(3.1) > Value::Float(2.4));
        assert!(Value::Float(9.6) == Value::Float(9.6));

        assert!(Value::Integer(124) < Value::Integer(234));
        assert!(Value::Integer(4) > Value::Integer(1));
        assert!(Value::Integer(839) == Value::Integer(839));
    }
}
<commit_msg>Corrected default display resolution<commit_after>use typedef::*;
use value::Value;

pub const PREAMBLE: &str = "BAKERVM";

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Target {
    Framebuffer(Address),
    ValueIndex(Address),
    Stack,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Instruction {
    Add(Target, Target),
    Sub(Target, Target),
    Div(Target, Target),
    Mul(Target, Target),
    Rem(Target, Target),

    Cmp(Target, Target),
    Jmp(Address),
    JmpLt(Address),
    JmpGt(Address),
    JmpEq(Address),
    JmpLtEq(Address),
    JmpGtEq(Address),

    Push(Target, Value),
    Mov(Target, Target),
    Swp(Target, Target),

    Call(Address),
    Ret,

    Halt,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DisplayResolution {
    pub width: usize,
    pub height: usize,
}

impl Default for DisplayResolution {
    fn default() -> Self {
        DisplayResolution {
            width: 320,
            height: 200,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct VMConfig {
    pub display_resolution: DisplayResolution,
    pub display_scale: Float,
    pub keyboard_enabled: bool,
    pub mouse_enabled: bool,
}

impl Default for VMConfig {
    fn default() -> Self {
        VMConfig {
            display_resolution: Default::default(),
            display_scale: 4.0,
            keyboard_enabled: true,
            mouse_enabled: true,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Program {
    pub preamble: String,
    pub version: String,
    pub config: VMConfig,
    pub instructions: Vec<Instruction>,
}

impl Default for Program {
    fn default() -> Self {
        Program {
            preamble: String::from(PREAMBLE),
            version: String::from(env!("CARGO_PKG_VERSION")),
            config: Default::default(),
            instructions: Default::default(),
        }
    }
}

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

    #[test]
    fn comparison() {
        assert!(Value::Float(1.3) < Value::Float(1.4));
        assert!(Value::Float(3.1) > Value::Float(2.4));
        assert!(Value::Float(9.6) == Value::Float(9.6));

        assert!(Value::Integer(124) < Value::Integer(234));
        assert!(Value::Integer(4) > Value::Integer(1));
        assert!(Value::Integer(839) == Value::Integer(839));
    }
}
<|endoftext|>


<commit_before>/// This module contains source for the `generate` command.
use exercise::Result;
use serde_json::Value as JsonValue;
use std::{
    collections::HashMap,
    fs::{self, File, OpenOptions},
    io::Write,
    path::Path,
    process::{Command, Stdio},
};

const GITIGNORE_CONTENT: &str = include_str!("defaults/gitignore");
const EXAMPLE_RS_CONTENT: &str = include_str!("defaults/example.rs");
const DESCRIPTION_MD_CONTENT: &str = include_str!("defaults/description.md");
const METADATA_YML_CONTENT: &str = include_str!("defaults/metadata.yml");

// Generate .meta directory and its contents without using the canonical data
fn generate_meta(exercise_name: &str, exercise_path: &Path) -> Result<()> {
    let meta_dir = exercise_path.join(".meta");
    fs::create_dir(&meta_dir)?;

    for (file, content) in [
        ("description.md", DESCRIPTION_MD_CONTENT),
        ("metadata.yml", METADATA_YML_CONTENT),
    ]
    .iter()
    {
        if !exercise::canonical_file_exists(exercise_name, file)? {
            fs::write(exercise_path.join(".meta").join(file), content)?;
        }
    }

    if fs::read_dir(&meta_dir)?.count() == 0 {
        fs::remove_dir(meta_dir)?;
    }

    Ok(())
}

// Generate test suite using the canonical data
fn generate_tests_from_canonical_data(
    exercise_name: &str,
    exercise_path: &Path,
    canonical_data: &JsonValue,
    use_maplit: bool,
) -> Result<()> {
    exercise::update_cargo_toml_version(exercise_name, canonical_data)?;

    let tests_path = exercise_path
        .join("tests")
        .join(format!("{}.rs", exercise_name));

    let tests_content = exercise::get_tests_content(exercise_name)?;

    let updated_tests_content = format!(
        "//! Tests for {exercise_name} \n\
        //! \n\
        //! Generated by [utility][utility] using [canonical data][canonical_data]\n\
        //! \n\
        //! [utility]: https://github.com/exercism/rust/tree/master/util/exercise\n\
        //! [canonical_data]: https://raw.githubusercontent.com/exercism/problem-specifications/master/exercises/{exercise_name}/canonical-data.json\n\
        \n\
        {} \n\
        ",
        tests_content,
        exercise_name=exercise_name,
    );

    fs::write(&tests_path, updated_tests_content)?;

    let mut property_functions: HashMap<&str, String> = HashMap::new();

    let mut test_functions: Vec<String> = Vec::new();

    for case in get!(canonical_data, "cases", as_array) {
        if let Some(sub_cases) = case.get("cases") {
            for sub_case in val_as!(sub_cases, as_array) {
                if let Some(property) = sub_case.get("property") {
                    let property = val_as!(property, as_str);
                    if !property_functions.contains_key(property) {
                        property_functions
                            .insert(property, exercise::generate_property_body(property));
                    }
                }

                test_functions.push(exercise::generate_test_function(&sub_case, use_maplit)?);
            }
        } else {
            if let Some(property) = case.get("property") {
                let property = val_as!(property, as_str);
                if !property_functions.contains_key(property) {
                    property_functions.insert(property, exercise::generate_property_body(property));
                }
            }

            test_functions.push(exercise::generate_test_function(&case, use_maplit)?);
        }
    }

    if !test_functions.is_empty() {
        let first_test_function = test_functions.remove(0).replace("#[ignore]\n", "");

        test_functions.insert(0, first_test_function);
    }

    let mut tests_file = OpenOptions::new().append(true).open(&tests_path)?;

    for (_, property_body) in &property_functions {
        tests_file.write_all(property_body.as_bytes())?;
    }

    tests_file.write_all(test_functions.join("\n\n").as_bytes())?;

    exercise::rustfmt(&tests_path)?;

    Ok(())
}

// Run bin/configlet generate command to generate README for the exercise
fn generate_readme(exercise_name: &str) -> Result<()> {
    println!(
        "Generating README for {} via 'bin/configlet generate'",
        exercise_name
    );

    let problem_specifications_path = Path::new(&*exercise::TRACK_ROOT)
        .join("..")
        .join("problem-specifications");

    if !problem_specifications_path.exists() {
        let problem_specifications_url = "https://github.com/exercism/problem-specifications.git";
        println!(
            "problem-specifications repository not found. Cloning the repository from {}",
            problem_specifications_url
        );

        Command::new("git")
            .current_dir(&*exercise::TRACK_ROOT)
            .stdout(Stdio::inherit())
            .arg("clone")
            .arg(problem_specifications_url)
            .arg(&problem_specifications_path)
            .output()?;
    }

    exercise::run_configlet_command(
        "generate",
        &[
            ".",
            "--only",
            exercise_name,
            "--spec-path",
            problem_specifications_path
                .to_str()
                .ok_or(format_err!("path inexpressable as str"))?,
        ],
    )?;

    Ok(())
}

// Generate a new exercise with specified name and flags
pub fn generate_exercise(exercise_name: &str, use_maplit: bool) -> Result<()> {
    if exercise::exercise_exists(exercise_name) {
        return Err(format_err!("exercise with the name {} already exists", exercise_name,).into());
    }

    let exercise_path = Path::new(&*exercise::TRACK_ROOT)
        .join("exercises")
        .join(exercise_name);

    println!(
        "Generating a new exercise at path: {}",
        exercise_path
            .to_str()
            .ok_or(format_err!("path inexpressable as str"))?
    );

    let _cargo_new_output = Command::new("cargo")
        .arg("new")
        .arg("--lib")
        .arg(
            exercise_path
                .to_str()
                .ok_or(format_err!("path inexpressable as str"))?,
        )
        .output()?;

    fs::write(exercise_path.join(".gitignore"), GITIGNORE_CONTENT)?;

    if use_maplit {
        let mut cargo_toml_file = OpenOptions::new()
            .append(true)
            .open(exercise_path.join("Cargo.toml"))?;

        cargo_toml_file.write_all(b"maplit = \"1.0.1\"")?;
    }

    fs::create_dir(exercise_path.join("tests"))?;

    let mut test_file = File::create(
        exercise_path
            .join("tests")
            .join(format!("{}.rs", exercise_name)),
    )?;

    if use_maplit {
        test_file.write_all(b"#[macro_use]\nextern crate maplit;\n")?;
    }

    test_file
        .write_all(&format!("extern crate {};\n", exercise_name.replace("-", "_")).into_bytes())?;

    test_file
        .write_all(&format!("use {}::*;\n\n", exercise_name.replace("-", "_")).into_bytes())?;

    fs::write(exercise_path.join("example.rs"), EXAMPLE_RS_CONTENT)?;

    match exercise::get_canonical_data(exercise_name) {
        Ok(canonical_data) => {
            println!("Generating tests from canonical data");

            generate_tests_from_canonical_data(
                &exercise_name,
                &exercise_path,
                &canonical_data,
                use_maplit,
            )?;
        }
        Err(_) => {
            println!(
                "No canonical data for exercise '{}' found. Generating standard exercise template.",
                &exercise_name
            );

            test_file.write_all(b"// Add your tests here\n")?;
        }
    }

    generate_meta(&exercise_name, &exercise_path)?;
    generate_readme(&exercise_name)?;

    Ok(())
}
<commit_msg>exercise crate: Made the generate subcommand to traverse an arbitrary-depth cases list<commit_after>/// This module contains source for the `generate` command.
use exercise::Result;
use serde_json::Value as JsonValue;
use std::{
    collections::HashMap,
    fs::{self, File, OpenOptions},
    io::Write,
    path::Path,
    process::{Command, Stdio},
};

const GITIGNORE_CONTENT: &str = include_str!("defaults/gitignore");
const EXAMPLE_RS_CONTENT: &str = include_str!("defaults/example.rs");
const DESCRIPTION_MD_CONTENT: &str = include_str!("defaults/description.md");
const METADATA_YML_CONTENT: &str = include_str!("defaults/metadata.yml");

// Generate .meta directory and its contents without using the canonical data
fn generate_meta(exercise_name: &str, exercise_path: &Path) -> Result<()> {
    let meta_dir = exercise_path.join(".meta");
    fs::create_dir(&meta_dir)?;

    for (file, content) in [
        ("description.md", DESCRIPTION_MD_CONTENT),
        ("metadata.yml", METADATA_YML_CONTENT),
    ]
        .iter()
    {
        if !exercise::canonical_file_exists(exercise_name, file)? {
            fs::write(exercise_path.join(".meta").join(file), content)?;
        }
    }

    if fs::read_dir(&meta_dir)?.count() == 0 {
        fs::remove_dir(meta_dir)?;
    }

    Ok(())
}

fn parse_case(
    case: &JsonValue,
    property_functions: &mut HashMap<String, String>,
    test_functions: &mut Vec<String>,
    use_maplit: bool,
) -> Result<()> {
    if let Some(sub_cases) = case.get("cases") {
        for sub_case in val_as!(sub_cases, as_array) {
            parse_case(&sub_case, property_functions, test_functions, use_maplit)?;
        }
    } else {
        if let Some(property) = case.get("property") {
            let property = val_as!(property, as_str);

            if !property_functions.contains_key(property) {
                property_functions.insert(
                    property.to_string(),
                    exercise::generate_property_body(property),
                );
            }
        }

        test_functions.push(exercise::generate_test_function(case, use_maplit)?);
    }

    Ok(())
}

// Generate test suite using the canonical data
fn generate_tests_from_canonical_data(
    exercise_name: &str,
    exercise_path: &Path,
    canonical_data: &JsonValue,
    use_maplit: bool,
) -> Result<()> {
    exercise::update_cargo_toml_version(exercise_name, canonical_data)?;

    let tests_path = exercise_path
        .join("tests")
        .join(format!("{}.rs", exercise_name));

    let tests_content = exercise::get_tests_content(exercise_name)?;

    let updated_tests_content = format!(
        "//! Tests for {exercise_name} \n\
        //! \n\
        //! Generated by [utility][utility] using [canonical data][canonical_data]\n\
        //! \n\
        //! [utility]: https://github.com/exercism/rust/tree/master/util/exercise\n\
        //! [canonical_data]: https://raw.githubusercontent.com/exercism/problem-specifications/master/exercises/{exercise_name}/canonical-data.json\n\
        \n\
        {} \n\
        ",
        tests_content,
        exercise_name=exercise_name,
    );

    fs::write(&tests_path, updated_tests_content)?;

    let mut property_functions: HashMap<String, String> = HashMap::new();

    let mut test_functions: Vec<String> = Vec::new();

    for case in get!(canonical_data, "cases", as_array) {
        parse_case(
            &case,
            &mut property_functions,
            &mut test_functions,
            use_maplit,
        )?;
    }

    if !test_functions.is_empty() {
        let first_test_function = test_functions.remove(0).replace("#[ignore]\n", "");

        test_functions.insert(0, first_test_function);
    }

    let mut tests_file = OpenOptions::new().append(true).open(&tests_path)?;

    for property_body in property_functions.values() {
        tests_file.write_all(property_body.as_bytes())?;
    }

    tests_file.write_all(test_functions.join("\n\n").as_bytes())?;

    exercise::rustfmt(&tests_path)?;

    Ok(())
}

// Run bin/configlet generate command to generate README for the exercise
fn generate_readme(exercise_name: &str) -> Result<()> {
    println!(
        "Generating README for {} via 'bin/configlet generate'",
        exercise_name
    );

    let problem_specifications_path = Path::new(&*exercise::TRACK_ROOT)
        .join("..")
        .join("problem-specifications");

    if !problem_specifications_path.exists() {
        let problem_specifications_url = "https://github.com/exercism/problem-specifications.git";
        println!(
            "problem-specifications repository not found. Cloning the repository from {}",
            problem_specifications_url
        );

        Command::new("git")
            .current_dir(&*exercise::TRACK_ROOT)
            .stdout(Stdio::inherit())
            .arg("clone")
            .arg(problem_specifications_url)
            .arg(&problem_specifications_path)
            .output()?;
    }

    exercise::run_configlet_command(
        "generate",
        &[
            ".",
            "--only",
            exercise_name,
            "--spec-path",
            problem_specifications_path
                .to_str()
                .ok_or(format_err!("path inexpressable as str"))?,
        ],
    )?;

    Ok(())
}

// Generate a new exercise with specified name and flags
pub fn generate_exercise(exercise_name: &str, use_maplit: bool) -> Result<()> {
    if exercise::exercise_exists(exercise_name) {
        return Err(format_err!("exercise with the name {} already exists", exercise_name,).into());
    }

    let exercise_path = Path::new(&*exercise::TRACK_ROOT)
        .join("exercises")
        .join(exercise_name);

    println!(
        "Generating a new exercise at path: {}",
        exercise_path
            .to_str()
            .ok_or(format_err!("path inexpressable as str"))?
    );

    let _cargo_new_output = Command::new("cargo")
        .arg("new")
        .arg("--lib")
        .arg(
            exercise_path
                .to_str()
                .ok_or(format_err!("path inexpressable as str"))?,
        ).output()?;

    fs::write(exercise_path.join(".gitignore"), GITIGNORE_CONTENT)?;

    if use_maplit {
        let mut cargo_toml_file = OpenOptions::new()
            .append(true)
            .open(exercise_path.join("Cargo.toml"))?;

        cargo_toml_file.write_all(b"maplit = \"1.0.1\"")?;
    }

    fs::create_dir(exercise_path.join("tests"))?;

    let mut test_file = File::create(
        exercise_path
            .join("tests")
            .join(format!("{}.rs", exercise_name)),
    )?;

    if use_maplit {
        test_file.write_all(b"#[macro_use]\nextern crate maplit;\n")?;
    }

    test_file
        .write_all(&format!("extern crate {};\n", exercise_name.replace("-", "_")).into_bytes())?;

    test_file
        .write_all(&format!("use {}::*;\n\n", exercise_name.replace("-", "_")).into_bytes())?;

    fs::write(exercise_path.join("example.rs"), EXAMPLE_RS_CONTENT)?;

    match exercise::get_canonical_data(exercise_name) {
        Ok(canonical_data) => {
            println!("Generating tests from canonical data");

            generate_tests_from_canonical_data(
                &exercise_name,
                &exercise_path,
                &canonical_data,
                use_maplit,
            )?;
        }
        Err(_) => {
            println!(
                "No canonical data for exercise '{}' found. Generating standard exercise template.",
                &exercise_name
            );

            test_file.write_all(b"// Add your tests here\n")?;
        }
    }

    generate_meta(&exercise_name, &exercise_path)?;
    generate_readme(&exercise_name)?;

    Ok(())
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::operators::*;
use timely::order::Product;

use differential_dataflow::input::Input;
use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::operators::group::Group;
use differential_dataflow::operators::join::JoinCore;
use differential_dataflow::operators::Iterate;
use differential_dataflow::operators::Consolidate;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let pre: usize = std::env::args().nth(4).unwrap().parse().unwrap();
    let inspect: bool = std::env::args().nth(5).unwrap() == "inspect";

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(6), move |worker| {

        let timer = ::std::time::Instant::now();

        let index = worker.index();
        let peers = worker.peers();

        let mut probe = timely::dataflow::operators::probe::Handle::new();

        // create a dataflow managing an ever-changing edge collection.
    	let mut graph = worker.dataflow::<Product<(),usize>,_,_>(|scope| {

            // create a source operator which will produce random edges and delete them.
            timely::dataflow::operators::generic::source(scope, "RandomGraph", |mut capability| {

                let seed: &[_] = &[1, 2, 3, index];
                let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
                let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

                let mut additions = 0;
                let mut deletions = 0;

                let handle = probe.clone();

                move |output| {

                    // do nothing if the probe is not caught up to us
                    if !handle.less_than(capability.time()) {

                        let mut time = capability.time().clone();
                        // println!("{:?}\tintroducing edges for batch starting {:?}", timer.elapsed(), time);

                        {   // scope to allow session to drop, un-borrow.
                            let mut session = output.session(&capability);

                            // we want to send at times.inner + (0 .. batch).
                            for _ in 0 .. batch {

                                while additions < time.inner + edges {
                                    if additions % peers == index {
                                        let src = rng1.gen_range(0, nodes);
                                        let dst = rng1.gen_range(0, nodes);
                                        session.give(((src, dst), time, 1));
                                    }
                                    additions += 1;
                                }
                                while deletions < time.inner {
                                    if deletions % peers == index {
                                        let src = rng2.gen_range(0, nodes);
                                        let dst = rng2.gen_range(0, nodes);
                                        session.give(((src, dst), time, -1));
                                    }
                                    deletions += 1;
                                }

                                time.inner += 1;
                            }
                        }

                        // println!("downgrading {:?} to {:?}", capability, time);
                        capability.downgrade(&time);
                    }
                }
            })
            .probe_with(&mut probe)
            .as_collection()
            .arrange_by_key()
            // .arrange::<OrdValSpineAbom>()
            .trace
        });

        println!("{:?}:\tloading edges", timer.elapsed());

        for _ in 0 .. pre {
            worker.step();
        }

        println!("{:?}\tedges loaded; building query dataflows", timer.elapsed());

        let mut roots = worker.dataflow(|scope| {

            let edges = graph.import(scope);
            let (input, roots) = scope.new_collection();
            let roots = roots.map(|x| (x, 0));

            // repeatedly update minimal distances each node can be reached from each root
            roots.iterate(|dists| {

                let edges = edges.enter(&dists.scope());
                let roots = roots.enter(&dists.scope());

                dists.arrange_by_key()
                     .join_core(&edges, |_k,l,d| Some((*d, l+1)))
                     .concat(&roots)
                     .group(|_, s, t| t.push((*s[0].0, 1)))
            })
            .map(|(_node, dist)| dist)
            .consolidate()
            .inspect(|x| println!("distance update: {:?}", x))
            .probe_with(&mut probe);

            input
        });

        let mut query = worker.dataflow(|scope| {

            let edges = graph.import(scope);
            let (input, query) = scope.new_collection();

            query.map(|x| (x, x))
                 .join_core(&edges, |_n, &q, &d| Some((d, q)))
                 .join_core(&edges, |_n, &q, &d| Some((d, q)))
                 .join_core(&edges, |_n, &q, &d| Some((d, q)))
                 .filter(move |_| inspect)
                 .map(|x| x.1)
                 .consolidate()
                 .inspect(|x| println!("{:?}", x))
                 .probe_with(&mut probe);

            input
        });

        println!("{:?}\tquery dataflows built; querying", timer.elapsed());

        // the trace will not compact unless we release capabilities.
        // we drop rather than continually downgrade them as we run.
        drop(graph);

        if batch > 0 {
            for round in 0 .. {

                let mut time = query.time().clone();

                // roots.insert(round % nodes);
                if index == 0 {
                    query.insert(round % nodes);
                }

                time.inner += batch;

                roots.advance_to(time); roots.flush();
                query.advance_to(time); query.flush();

                if index == 0 {
                    query.remove(round % nodes);
                }

                worker.step_while(|| probe.less_than(&time));

                println!("{:?}\tquery round {:?} complete", timer.elapsed(), round);
            }
        }
    }).unwrap();
}<commit_msg>update example<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::operators::*;
use timely::order::Product;

use differential_dataflow::input::Input;
use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::operators::group::Group;
use differential_dataflow::operators::join::JoinCore;
use differential_dataflow::operators::Iterate;
use differential_dataflow::operators::Consolidate;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let pre: usize = std::env::args().nth(4).unwrap().parse().unwrap();
    let inspect: bool = std::env::args().nth(5).unwrap() == "inspect";

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(6), move |worker| {

        let timer = ::std::time::Instant::now();

        let index = worker.index();
        let peers = worker.peers();

        let mut probe = timely::dataflow::operators::probe::Handle::new();

        // create a dataflow managing an ever-changing edge collection.
    	let mut graph = worker.dataflow::<Product<(),usize>,_,_>(|scope| {

            // create a source operator which will produce random edges and delete them.
            timely::dataflow::operators::generic::source(scope, "RandomGraph", |mut capability, _info| {

                let seed: &[_] = &[1, 2, 3, index];
                let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
                let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

                let mut additions = 0;
                let mut deletions = 0;

                let handle = probe.clone();

                move |output| {

                    // do nothing if the probe is not caught up to us
                    if !handle.less_than(capability.time()) {

                        let mut time = capability.time().clone();
                        // println!("{:?}\tintroducing edges for batch starting {:?}", timer.elapsed(), time);

                        {   // scope to allow session to drop, un-borrow.
                            let mut session = output.session(&capability);

                            // we want to send at times.inner + (0 .. batch).
                            for _ in 0 .. batch {

                                while additions < time.inner + edges {
                                    if additions % peers == index {
                                        let src = rng1.gen_range(0, nodes);
                                        let dst = rng1.gen_range(0, nodes);
                                        session.give(((src, dst), time, 1));
                                    }
                                    additions += 1;
                                }
                                while deletions < time.inner {
                                    if deletions % peers == index {
                                        let src = rng2.gen_range(0, nodes);
                                        let dst = rng2.gen_range(0, nodes);
                                        session.give(((src, dst), time, -1));
                                    }
                                    deletions += 1;
                                }

                                time.inner += 1;
                            }
                        }

                        // println!("downgrading {:?} to {:?}", capability, time);
                        capability.downgrade(&time);
                    }
                }
            })
            .probe_with(&mut probe)
            .as_collection()
            .arrange_by_key()
            // .arrange::<OrdValSpineAbom>()
            .trace
        });

        println!("{:?}:\tloading edges", timer.elapsed());

        for _ in 0 .. pre {
            worker.step();
        }

        println!("{:?}\tedges loaded; building query dataflows", timer.elapsed());

        let mut roots = worker.dataflow(|scope| {

            let edges = graph.import(scope);
            let (input, roots) = scope.new_collection();
            let roots = roots.map(|x| (x, 0));

            // repeatedly update minimal distances each node can be reached from each root
            roots.iterate(|dists| {

                let edges = edges.enter(&dists.scope());
                let roots = roots.enter(&dists.scope());

                dists.arrange_by_key()
                     .join_core(&edges, |_k,l,d| Some((*d, l+1)))
                     .concat(&roots)
                     .group(|_, s, t| t.push((*s[0].0, 1)))
            })
            .map(|(_node, dist)| dist)
            .consolidate()
            .inspect(|x| println!("distance update: {:?}", x))
            .probe_with(&mut probe);

            input
        });

        let mut query = worker.dataflow(|scope| {

            let edges = graph.import(scope);
            let (input, query) = scope.new_collection();

            query.map(|x| (x, x))
                 .join_core(&edges, |_n, &q, &d| Some((d, q)))
                 .join_core(&edges, |_n, &q, &d| Some((d, q)))
                 .join_core(&edges, |_n, &q, &d| Some((d, q)))
                 .filter(move |_| inspect)
                 .map(|x| x.1)
                 .consolidate()
                 .inspect(|x| println!("{:?}", x))
                 .probe_with(&mut probe);

            input
        });

        println!("{:?}\tquery dataflows built; querying", timer.elapsed());

        // the trace will not compact unless we release capabilities.
        // we drop rather than continually downgrade them as we run.
        drop(graph);

        if batch > 0 {
            for round in 0 .. {

                let mut time = query.time().clone();

                // roots.insert(round % nodes);
                if index == 0 {
                    query.insert(round % nodes);
                }

                time.inner += batch;

                roots.advance_to(time); roots.flush();
                query.advance_to(time); query.flush();

                if index == 0 {
                    query.remove(round % nodes);
                }

                worker.step_while(|| probe.less_than(&time));

                println!("{:?}\tquery round {:?} complete", timer.elapsed(), round);
            }
        }
    }).unwrap();
}<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::input::Input;
use differential_dataflow::operators::count::CountTotal;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    let inspect: bool = std::env::args().find(|x| x == "inspect").is_some();

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let timer = ::std::time::Instant::now();

        let index = worker.index();
        let peers = worker.peers();

        // create a a degree counting differential dataflow
        let (mut input, probe) = worker.dataflow(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_collection();

            let degrs = edges.map(|(src, _dst)| src)
                             .count_total();

            // pull of count, and count.
            let distr = degrs.map(|(_src, cnt)| cnt as usize)
                             .count_total();

            // show us something about the collection, notice when done.
            let probe = if inspect {
                distr.inspect(|x| println!("observed: {:?}", x))
                     .probe()
            }
            else { distr.probe() };

            (input, probe)
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions

        // load up graph dataz
        for _ in 0 .. (edges / peers) + if index < (edges % peers) { 1 } else { 0 } {
            input.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)))
        }

        input.advance_to(1u64);
        input.flush();
        worker.step_while(|| probe.less_than(input.time()));

        println!("round 0 finished after {:?} (loading)", timer.elapsed());

        if batch > 0 {

            if !::std::env::args().any(|x| x == "open-loop") {

                // closed-loop latency-throughput test, parameterized by batch size.
                let timer = ::std::time::Instant::now();
                let mut wave = 1;
                while timer.elapsed().as_secs() < 10 {
                    for round in 0 .. batch {
                        input.advance_to((((wave * batch) + round) * peers + index) as u64);
                        input.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                        input.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                    }

                    wave += 1;
                    input.advance_to((wave * batch * peers) as u64);
                    input.flush();
                    worker.step_while(|| probe.less_than(input.time()));
                }

                let elapsed = timer.elapsed();
                let seconds = elapsed.as_secs() as f64 + (elapsed.subsec_nanos() as f64) / 1000000000.0;
                println!("{:?}, {:?}", seconds / (wave - 1) as f64, ((wave - 1) * batch * peers) as f64 / seconds);

            }
            else {

                let requests_per_sec = batch;
                let ns_per_request = 1_000_000_000 / requests_per_sec;
                let mut request_counter = peers + index;    // skip first request for each.
                let mut measurements = Vec::with_capacity(20 * requests_per_sec / peers);

                let timer = ::std::time::Instant::now();

                let measurements_per_sec = requests_per_sec / peers;

                while measurements.len() < measurements_per_sec * 21 {

                    // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
                    let elapsed = timer.elapsed();
                    let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                    // Introduce any requests that have "arrived" since last we were here.
                    // Request i "arrives" at `index + ns_per_request * (i + 1)`.
                    while (((index + request_counter) * ns_per_request) as u64) < elapsed_ns {
                        input.advance_to(((index + request_counter) * ns_per_request) as u64);
                        input.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                        input.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                        request_counter += peers;
                    }
                    input.advance_to(elapsed_ns);
                    input.flush();

                    while probe.less_than(input.time()) {
                        worker.step();
                    }

                    // Determine completed ns.
                    let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0].inner);

                    let elapsed = timer.elapsed();
                    let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                    // any un-recorded measurements that are complete should be recorded.
                    while (((index + peers * (measurements.len() + 1)) * ns_per_request) as u64) < acknowledged_ns {
                        let requested_at = ((index + peers * (measurements.len() + 1)) * ns_per_request) as u64;
                        measurements.push(elapsed_ns - requested_at);
                    }
                }

                measurements.truncate(20 * measurements_per_sec);
                measurements.drain(0 .. (10 * measurements_per_sec));
                measurements.sort();

                let min = measurements[0];
                let med = measurements[measurements.len() / 2];
                let p99 = measurements[99 * measurements.len() / 100];
                let max = measurements[measurements.len() - 1];

                println!("{}\t{}\t{}\t{}\t(of {} measurements)", min, med, p99, max, measurements.len());
            }
        }
    }).unwrap();
}<commit_msg>add worker identifier<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::input::Input;
use differential_dataflow::operators::count::CountTotal;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    let inspect: bool = std::env::args().find(|x| x == "inspect").is_some();

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let timer = ::std::time::Instant::now();

        let index = worker.index();
        let peers = worker.peers();

        // create a a degree counting differential dataflow
        let (mut input, probe) = worker.dataflow(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_collection();

            let degrs = edges.map(|(src, _dst)| src)
                             .count_total();

            // pull of count, and count.
            let distr = degrs.map(|(_src, cnt)| cnt as usize)
                             .count_total();

            // show us something about the collection, notice when done.
            let probe = if inspect {
                distr.inspect(|x| println!("observed: {:?}", x))
                     .probe()
            }
            else { distr.probe() };

            (input, probe)
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions

        // load up graph dataz
        for _ in 0 .. (edges / peers) + if index < (edges % peers) { 1 } else { 0 } {
            input.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)))
        }

        input.advance_to(1u64);
        input.flush();
        worker.step_while(|| probe.less_than(input.time()));

        println!("round 0 finished after {:?} (loading)", timer.elapsed());

        if batch > 0 {

            if !::std::env::args().any(|x| x == "open-loop") {

                // closed-loop latency-throughput test, parameterized by batch size.
                let timer = ::std::time::Instant::now();
                let mut wave = 1;
                while timer.elapsed().as_secs() < 10 {
                    for round in 0 .. batch {
                        input.advance_to((((wave * batch) + round) * peers + index) as u64);
                        input.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                        input.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                    }

                    wave += 1;
                    input.advance_to((wave * batch * peers) as u64);
                    input.flush();
                    worker.step_while(|| probe.less_than(input.time()));
                }

                let elapsed = timer.elapsed();
                let seconds = elapsed.as_secs() as f64 + (elapsed.subsec_nanos() as f64) / 1000000000.0;
                println!("{:?}, {:?}", seconds / (wave - 1) as f64, ((wave - 1) * batch * peers) as f64 / seconds);

            }
            else {

                let requests_per_sec = batch;
                let ns_per_request = 1_000_000_000 / requests_per_sec;
                let mut request_counter = peers + index;    // skip first request for each.
                let mut measurements = Vec::with_capacity(20 * requests_per_sec / peers);

                let timer = ::std::time::Instant::now();

                let measurements_per_sec = requests_per_sec / peers;

                while measurements.len() < measurements_per_sec * 21 {

                    // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
                    let elapsed = timer.elapsed();
                    let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                    // Introduce any requests that have "arrived" since last we were here.
                    // Request i "arrives" at `index + ns_per_request * (i + 1)`.
                    while (((index + request_counter) * ns_per_request) as u64) < elapsed_ns {
                        input.advance_to(((index + request_counter) * ns_per_request) as u64);
                        input.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                        input.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                        request_counter += peers;
                    }
                    input.advance_to(elapsed_ns);
                    input.flush();

                    while probe.less_than(input.time()) {
                        worker.step();
                    }

                    // Determine completed ns.
                    let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0].inner);

                    let elapsed = timer.elapsed();
                    let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                    // any un-recorded measurements that are complete should be recorded.
                    while (((index + peers * (measurements.len() + 1)) * ns_per_request) as u64) < acknowledged_ns {
                        let requested_at = ((index + peers * (measurements.len() + 1)) * ns_per_request) as u64;
                        measurements.push(elapsed_ns - requested_at);
                    }
                }

                measurements.truncate(20 * measurements_per_sec);
                measurements.drain(0 .. (10 * measurements_per_sec));
                measurements.sort();

                let min = measurements[0];
                let med = measurements[measurements.len() / 2];
                let p99 = measurements[99 * measurements.len() / 100];
                let max = measurements[measurements.len() - 1];

                println!("worker {}:\t{}\t{}\t{}\t{}\t(of {} measurements)", index, min, med, p99, max, measurements.len());
            }
        }
    }).unwrap();
}<|endoftext|>


<commit_before>extern crate libffi;

use libffi::middle::types::Type;

fn main() {
    Type::structure(vec![
        Type::u16(),
        Type::u16(),
    ].into_iter());
}
<commit_msg>Tests pass.<commit_after>extern crate libffi;

use libffi::middle::Type;

fn main() {
    Type::structure(vec![
        Type::u16(),
        Type::u16(),
    ].into_iter());
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::path::BytesContainer;
use std::io::{Command, fs, USER_RWX};
use std::os;

fn main() {
    // If we're the child, make sure we were invoked correctly
    let args = os::args();
    if args.len() > 1 && args[1].as_slice() == "child" {
        return assert_eq!(args[0],
                          format!("mytest{}", os::consts::EXE_SUFFIX));
    }

    test();
}

fn test() {
    // If we're the parent, copy our own binary to a new directory.
    let my_path = os::self_exe_name().unwrap();
    let my_dir  = my_path.dir_path();

    let child_dir = Path::new(my_dir.join("issue-15149-child"));
    drop(fs::mkdir(&child_dir, USER_RWX));

    let child_path = child_dir.join(format!("mytest{}",
                                            os::consts::EXE_SUFFIX));
    fs::copy(&my_path, &child_path).unwrap();

    // Append the new directory to our own PATH.
    let mut path = os::split_paths(os::getenv("PATH").unwrap_or(String::new()));
    path.push(child_dir.clone());
    let path = os::join_paths(path.as_slice()).unwrap();

    let child_output = Command::new("mytest").env("PATH", path.as_slice())
                                             .arg("child")
                                             .output().unwrap();

    assert!(child_output.status.success(),
            format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
                    child_output.output.container_as_str().unwrap(),
                    child_output.error.container_as_str().unwrap()));
}
<commit_msg>Add a random number string to the end of the issue-15149 test's child directory's name, and remove the directory after a successful test.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::{Command, fs, USER_RWX};
use std::os;
use std::path::BytesContainer;
use std::rand::random;

fn main() {
    // If we're the child, make sure we were invoked correctly
    let args = os::args();
    if args.len() > 1 && args[1].as_slice() == "child" {
        return assert_eq!(args[0],
                          format!("mytest{}", os::consts::EXE_SUFFIX));
    }

    test();
}

fn test() {
    // If we're the parent, copy our own binary to a new directory.
    let my_path = os::self_exe_name().unwrap();
    let my_dir  = my_path.dir_path();

    let random_u32: u32 = random();
    let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}",
                                                  random_u32)));
    fs::mkdir(&child_dir, USER_RWX).unwrap();

    let child_path = child_dir.join(format!("mytest{}",
                                            os::consts::EXE_SUFFIX));
    fs::copy(&my_path, &child_path).unwrap();

    // Append the new directory to our own PATH.
    let mut path = os::split_paths(os::getenv("PATH").unwrap_or(String::new()));
    path.push(child_dir.clone());
    let path = os::join_paths(path.as_slice()).unwrap();

    let child_output = Command::new("mytest").env("PATH", path.as_slice())
                                             .arg("child")
                                             .output().unwrap();

    assert!(child_output.status.success(),
            format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
                    child_output.output.container_as_str().unwrap(),
                    child_output.error.container_as_str().unwrap()));

    fs::rmdir_recursive(&child_dir).unwrap();

}
<|endoftext|>