<commit_before>extern crate bytes;
extern crate env_logger;
extern crate mio;
#[macro_use]
extern crate log;
#[macro_use]
extern crate clap;
extern crate failure;
extern crate slab;

use clap::{App, Arg};
use failure::Error;
use failure::ResultExt;
use mio::net::{TcpListener, TcpStream};
use slab::Slab;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::ops;

#[derive(Debug)]
enum MiChatCommand {
    Broadcast(String),
    NewConnection(TcpStream),
    CloseConnection,
}

struct MiChat {
    connections: Slab<EventHandler>,
}

trait RuleHandler {
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready);
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error>;
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error>;
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error>;
}

impl MiChat {
    fn new() -> MiChat {
        MiChat {
            connections: Slab::new(),
        }
    }

    fn listen(&mut self, event_loop: &mut mio::Poll, listener: TcpListener) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Listener(Listener::new(listener, token));
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn process_action(
        &mut self,
        src: usize,
        msg: MiChatCommand,
        event_loop: &mut mio::Poll,
    ) -> Result<(), Error> {
        trace!("{:p}; from {:?}; got {:?}", self, src, msg);
        match msg {
            MiChatCommand::Broadcast(s) => self.process_broadcast(s)?,
            MiChatCommand::NewConnection(socket) => {
                self.process_new_connection(event_loop, socket)?
            }
            MiChatCommand::CloseConnection => self.process_close(src, event_loop)?,
        }
        Ok(())
    }

    fn process_broadcast(&mut self, s: String) -> Result<(), Error> {
        for c in self.client_connections_mut() {
            c.enqueue(&s);
        }
        Ok(())
    }

    fn process_new_connection(
        &mut self,
        event_loop: &mut mio::Poll,
        socket: mio::tcp::TcpStream,
    ) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Conn(Connection::new(socket, token)?);
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn process_close(&mut self, src: usize, event_loop: &mut mio::Poll) -> Result<(), Error> {
        debug!("Processing close: {:?}", src);
        let conn = self.connections.remove(src);
        conn.deregister(event_loop)?;
        Ok(())
    }

    fn client_connections_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut Connection> + 'a {
        self.connections.iter_mut().filter_map(|(_, it)| match it {
            &mut EventHandler::Conn(ref mut c) => Some(c),
            _ => None,
        })
    }
}

#[derive(Debug)]
struct Connection {
    socket: TcpStream,
    peer: std::net::SocketAddr,
    sock_status: mio::Ready,
    token: mio::Token,
    read_buf: Vec<u8>,
    read_eof: bool,
    write_buf: Vec<u8>,
}

impl RuleHandler for Connection {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.socket,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("event loop register")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.socket)?;
        Ok(())
    }

    // Event updates arrive here
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        self.sock_status.insert(events);
        info!(
            "Connection::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.peer, events, self.sock_status
        );
    }

    // actions are processed here on down.

    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            self.sock_status.remove(mio::Ready::readable());
            self.read()?;
        }

        self.process_buffer(to_parent);

        if self.sock_status.is_writable() {
            self.sock_status.remove(mio::Ready::writable());
            self.write()?;
        }

        if self.should_close() {
            to_parent(MiChatCommand::CloseConnection)
        } else {
            self.reregister(event_loop)?;
        }

        Ok(())
    }
}

impl Connection {
    fn new(socket: TcpStream, token: mio::Token) -> Result<Connection, Error> {
        let peer = socket.peer_addr()?;
        Ok(Connection {
            socket: socket,
            peer: peer,
            sock_status: mio::Ready::empty(),
            token: token,
            read_buf: Vec::with_capacity(1024),
            write_buf: Vec::new(),
            read_eof: false,
        })
    }
    fn process_buffer(&mut self, to_parent: &mut FnMut(MiChatCommand)) {
        let mut prev = 0;
        info!("{:?}: Read buffer: {:?}", self.peer, self.read_buf);
        for n in self.read_buf.iter().enumerate().filter_map(|(i, e)| {
            if *e == '\n' as u8 {
                Some(i)
            } else {
                None
            }
        }) {
            info!(
                "{:?}: Pos: {:?}; chunk: {:?}",
                self.peer,
                n,
                &self.read_buf[prev..n]
            );
            let s = String::from_utf8_lossy(&self.read_buf[prev..n]).to_string();
            let cmd = MiChatCommand::Broadcast(s);
            info!("Send! {:?}", cmd);
            to_parent(cmd);
            prev = n + 1;
        }
        let remainder = self.read_buf[prev..].to_vec();
        info!("{:?}: read Remainder: {}", self.peer, remainder.len());
        self.read_buf = remainder;
    }

    fn read(&mut self) -> Result<(), Error> {
        let mut abuf = vec![0; 1024];
        match self.socket.read(&mut abuf).context("Reading socket")? {
            0 => {
                info!("{:?}: EOF!", self.peer);
                self.read_eof = true;
                Ok(())
            }
            n => {
                info!("{:?}: Read {}bytes", self.peer, n);
                self.read_buf.extend(&abuf[0..n]);
                Ok(())
            }
        }
    }

    fn write(&mut self) -> Result<(), Error> {
        let n = self
            .socket
            .write(&mut self.write_buf)
            .context("writing buffer")?;
        info!(
            "{:?}: Wrote {} of {} in buffer",
            self.peer,
            n,
            self.write_buf.len()
        );
        self.write_buf = self.write_buf[n..].to_vec();
        info!("{:?}: Now {:?}b", self.peer, self.write_buf.len());
        Ok(())
    }

    fn should_close(&self) -> bool {
        self.read_eof && self.write_buf.is_empty()
    }

    fn reregister(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut flags = mio::Ready::readable();
        if !self.write_buf.is_empty() {
            flags.insert(mio::Ready::writable());
        }
        info!("Registering {:?} with {:?}", self, flags);

        event_loop
            .reregister(&self.socket, self.token, flags, mio::PollOpt::oneshot())
            .context("EventLoop#reregister")?;

        Ok(())
    }

    fn enqueue(&mut self, s: &str) {
        self.write_buf.extend(s.as_bytes());
        self.write_buf.push('\n' as u8);
    }
}

#[derive(Debug)]
struct Listener {
    listener: TcpListener,
    sock_status: mio::Ready,
    token: mio::Token,
}

impl Listener {
    fn new(listener: TcpListener, token: mio::Token) -> Listener {
        Listener {
            listener: listener,
            sock_status: mio::Ready::empty(),
            token: token,
        }
    }
    fn reregister(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .reregister(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("Register listener")?;
        Ok(())
    }
}

impl RuleHandler for Listener {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("Register listener")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.listener)?;
        Ok(())
    }

    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        assert!(events.is_readable());
        self.sock_status.insert(events);
        info!(
            "Listener::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.listener.local_addr(),
            events,
            self.sock_status
        );
    }
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            info!("the listener socket is ready to accept a connection");
            self.sock_status.remove(mio::Ready::readable());
            let (socket, _client) = self.listener.accept().context("Accept listening socket")?;
            let cmd = MiChatCommand::NewConnection(socket);
            to_parent(cmd);

            self.reregister(event_loop, self.token)?;
        }
        Ok(())
    }
}

#[derive(Debug)]
enum EventHandler {
    Listener(Listener),
    Conn(Connection),
}

impl ops::Deref for EventHandler {
    type Target = RuleHandler;
    fn deref(&self) -> &Self::Target {
        match self {
            &EventHandler::Conn(ref conn) => conn,
            &EventHandler::Listener(ref listener) => listener,
        }
    }
}
impl ops::DerefMut for EventHandler {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            &mut EventHandler::Conn(ref mut conn) => conn,
            &mut EventHandler::Listener(ref mut listener) => listener,
        }
    }
}

impl MiChat {
    fn ready(&mut self, event_loop: &mut mio::Poll, token: mio::Token, events: mio::Ready) {
        info!("{:?}: {:?}", token, events);
        self.connections[token.into()].handle_event(event_loop, events);
    }

    fn process(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut parent_actions = VecDeque::new();
        let mut failed = Vec::new();
        loop {
            let mut something_done = false;
            for (idx, conn) in self.connections.iter_mut() {
                if let Err(e) = conn.process_rules(event_loop, &mut |action| {
                    parent_actions.push_back((idx, action))
                }) {
                    failed.push(idx);
                    error!("Error on connection {:?}; Dropping: {:?}", idx, e);
                }
            }
            for idx in failed.drain(..) {
                debug!("Remove failed; {:?}", idx);
                let conn = self.connections.remove(idx);
                conn.deregister(event_loop)?;
            }
            for (src, action) in parent_actions.drain(..) {
                something_done = true;
                if let Err(e) = self.process_action(src, action, event_loop) {
                    failed.push(src);
                    error!("Error on action for {:?}; Dropping: {:?}", src, e);
                }
            }
            // If we didn't do anything, we're done.
            if !something_done {
                break;
            }
        }

        Ok(())
    }

    fn run(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        loop {
            self.run_once(event_loop)?;
        }
    }
    fn run_once(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut events = mio::Events::with_capacity(1024);
        event_loop.poll(&mut events, None)?;
        for ev in &events {
            self.ready(event_loop, ev.token(), ev.readiness())
        }

        self.process(event_loop)
    }
}

fn main() {
    env_logger::init();
    let matches = App::new("michat")
        .arg(
            Arg::with_name("bind")
                .short("l")
                .takes_value(true)
                .required(true),
        ).get_matches();

    let address = value_t_or_exit!(matches.value_of("bind"), std::net::SocketAddr);
    let listener = TcpListener::bind(&address).expect("bind");

    let mut event_loop = mio::Poll::new().expect("Create event loop");
    let mut service = MiChat::new();

    service
        .listen(&mut event_loop, listener)
        .expect("Starting listener");
    info!("running michat listener at: {:?}", address);
    service.run(&mut event_loop).expect("run");
}
<commit_msg>rustfmt.<commit_after>extern crate bytes;
extern crate env_logger;
extern crate mio;
#[macro_use]
extern crate log;
#[macro_use]
extern crate clap;
extern crate failure;
extern crate slab;

use clap::{App, Arg};
use failure::Error;
use failure::ResultExt;
use mio::net::{TcpListener, TcpStream};
use slab::Slab;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::ops;

#[derive(Debug)]
enum MiChatCommand {
    Broadcast(String),
    NewConnection(TcpStream),
    CloseConnection,
}

struct MiChat {
    connections: Slab<EventHandler>,
}

trait RuleHandler {
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready);
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error>;
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error>;
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error>;
}

impl MiChat {
    fn new() -> MiChat {
        MiChat {
            connections: Slab::new(),
        }
    }

    fn listen(&mut self, event_loop: &mut mio::Poll, listener: TcpListener) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Listener(Listener::new(listener, token));
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn process_action(
        &mut self,
        src: usize,
        msg: MiChatCommand,
        event_loop: &mut mio::Poll,
    ) -> Result<(), Error> {
        trace!("{:p}; from {:?}; got {:?}", self, src, msg);
        match msg {
            MiChatCommand::Broadcast(s) => self.process_broadcast(s)?,
            MiChatCommand::NewConnection(socket) => {
                self.process_new_connection(event_loop, socket)?
            }
            MiChatCommand::CloseConnection => self.process_close(src, event_loop)?,
        }
        Ok(())
    }

    fn process_broadcast(&mut self, s: String) -> Result<(), Error> {
        for c in self.client_connections_mut() {
            c.enqueue(&s);
        }
        Ok(())
    }

    fn process_new_connection(
        &mut self,
        event_loop: &mut mio::Poll,
        socket: mio::tcp::TcpStream,
    ) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Conn(Connection::new(socket, token)?);
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn process_close(&mut self, src: usize, event_loop: &mut mio::Poll) -> Result<(), Error> {
        debug!("Processing close: {:?}", src);
        let conn = self.connections.remove(src);
        conn.deregister(event_loop)?;
        Ok(())
    }

    fn client_connections_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut Connection> + 'a {
        self.connections.iter_mut().filter_map(|(_, it)| match it {
            &mut EventHandler::Conn(ref mut c) => Some(c),
            _ => None,
        })
    }
}

#[derive(Debug)]
struct Connection {
    socket: TcpStream,
    peer: std::net::SocketAddr,
    sock_status: mio::Ready,
    token: mio::Token,
    read_buf: Vec<u8>,
    read_eof: bool,
    write_buf: Vec<u8>,
}

impl RuleHandler for Connection {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.socket,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            )
            .context("event loop register")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.socket)?;
        Ok(())
    }

    // Event updates arrive here
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        self.sock_status.insert(events);
        info!(
            "Connection::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.peer, events, self.sock_status
        );
    }

    // actions are processed here on down.

    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            self.sock_status.remove(mio::Ready::readable());
            self.read()?;
        }

        self.process_buffer(to_parent);

        if self.sock_status.is_writable() {
            self.sock_status.remove(mio::Ready::writable());
            self.write()?;
        }

        if self.should_close() {
            to_parent(MiChatCommand::CloseConnection)
        } else {
            self.reregister(event_loop)?;
        }

        Ok(())
    }
}

impl Connection {
    fn new(socket: TcpStream, token: mio::Token) -> Result<Connection, Error> {
        let peer = socket.peer_addr()?;
        Ok(Connection {
            socket: socket,
            peer: peer,
            sock_status: mio::Ready::empty(),
            token: token,
            read_buf: Vec::with_capacity(1024),
            write_buf: Vec::new(),
            read_eof: false,
        })
    }
    fn process_buffer(&mut self, to_parent: &mut FnMut(MiChatCommand)) {
        let mut prev = 0;
        info!("{:?}: Read buffer: {:?}", self.peer, self.read_buf);
        for n in self.read_buf.iter().enumerate().filter_map(|(i, e)| {
            if *e == '\n' as u8 {
                Some(i)
            } else {
                None
            }
        }) {
            info!(
                "{:?}: Pos: {:?}; chunk: {:?}",
                self.peer,
                n,
                &self.read_buf[prev..n]
            );
            let s = String::from_utf8_lossy(&self.read_buf[prev..n]).to_string();
            let cmd = MiChatCommand::Broadcast(s);
            info!("Send! {:?}", cmd);
            to_parent(cmd);
            prev = n + 1;
        }
        let remainder = self.read_buf[prev..].to_vec();
        info!("{:?}: read Remainder: {}", self.peer, remainder.len());
        self.read_buf = remainder;
    }

    fn read(&mut self) -> Result<(), Error> {
        let mut abuf = vec![0; 1024];
        match self.socket.read(&mut abuf).context("Reading socket")? {
            0 => {
                info!("{:?}: EOF!", self.peer);
                self.read_eof = true;
                Ok(())
            }
            n => {
                info!("{:?}: Read {}bytes", self.peer, n);
                self.read_buf.extend(&abuf[0..n]);
                Ok(())
            }
        }
    }

    fn write(&mut self) -> Result<(), Error> {
        let n = self
            .socket
            .write(&mut self.write_buf)
            .context("writing buffer")?;
        info!(
            "{:?}: Wrote {} of {} in buffer",
            self.peer,
            n,
            self.write_buf.len()
        );
        self.write_buf = self.write_buf[n..].to_vec();
        info!("{:?}: Now {:?}b", self.peer, self.write_buf.len());
        Ok(())
    }

    fn should_close(&self) -> bool {
        self.read_eof && self.write_buf.is_empty()
    }

    fn reregister(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut flags = mio::Ready::readable();
        if !self.write_buf.is_empty() {
            flags.insert(mio::Ready::writable());
        }
        info!("Registering {:?} with {:?}", self, flags);

        event_loop
            .reregister(&self.socket, self.token, flags, mio::PollOpt::oneshot())
            .context("EventLoop#reregister")?;

        Ok(())
    }

    fn enqueue(&mut self, s: &str) {
        self.write_buf.extend(s.as_bytes());
        self.write_buf.push('\n' as u8);
    }
}

#[derive(Debug)]
struct Listener {
    listener: TcpListener,
    sock_status: mio::Ready,
    token: mio::Token,
}

impl Listener {
    fn new(listener: TcpListener, token: mio::Token) -> Listener {
        Listener {
            listener: listener,
            sock_status: mio::Ready::empty(),
            token: token,
        }
    }
    fn reregister(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .reregister(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            )
            .context("Register listener")?;
        Ok(())
    }
}

impl RuleHandler for Listener {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            )
            .context("Register listener")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.listener)?;
        Ok(())
    }

    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        assert!(events.is_readable());
        self.sock_status.insert(events);
        info!(
            "Listener::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.listener.local_addr(),
            events,
            self.sock_status
        );
    }
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            info!("the listener socket is ready to accept a connection");
            self.sock_status.remove(mio::Ready::readable());
            let (socket, _client) = self.listener.accept().context("Accept listening socket")?;
            let cmd = MiChatCommand::NewConnection(socket);
            to_parent(cmd);

            self.reregister(event_loop, self.token)?;
        }
        Ok(())
    }
}

#[derive(Debug)]
enum EventHandler {
    Listener(Listener),
    Conn(Connection),
}

impl ops::Deref for EventHandler {
    type Target = RuleHandler;
    fn deref(&self) -> &Self::Target {
        match self {
            &EventHandler::Conn(ref conn) => conn,
            &EventHandler::Listener(ref listener) => listener,
        }
    }
}
impl ops::DerefMut for EventHandler {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            &mut EventHandler::Conn(ref mut conn) => conn,
            &mut EventHandler::Listener(ref mut listener) => listener,
        }
    }
}

impl MiChat {
    fn ready(&mut self, event_loop: &mut mio::Poll, token: mio::Token, events: mio::Ready) {
        info!("{:?}: {:?}", token, events);
        self.connections[token.into()].handle_event(event_loop, events);
    }

    fn process(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut parent_actions = VecDeque::new();
        let mut failed = Vec::new();
        loop {
            let mut something_done = false;
            for (idx, conn) in self.connections.iter_mut() {
                if let Err(e) = conn.process_rules(event_loop, &mut |action| {
                    parent_actions.push_back((idx, action))
                }) {
                    failed.push(idx);
                    error!("Error on connection {:?}; Dropping: {:?}", idx, e);
                }
            }
            for idx in failed.drain(..) {
                debug!("Remove failed; {:?}", idx);
                let conn = self.connections.remove(idx);
                conn.deregister(event_loop)?;
            }
            for (src, action) in parent_actions.drain(..) {
                something_done = true;
                if let Err(e) = self.process_action(src, action, event_loop) {
                    failed.push(src);
                    error!("Error on action for {:?}; Dropping: {:?}", src, e);
                }
            }
            // If we didn't do anything, we're done.
            if !something_done {
                break;
            }
        }

        Ok(())
    }

    fn run(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        loop {
            self.run_once(event_loop)?;
        }
    }
    fn run_once(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut events = mio::Events::with_capacity(1024);
        event_loop.poll(&mut events, None)?;
        for ev in &events {
            self.ready(event_loop, ev.token(), ev.readiness())
        }

        self.process(event_loop)
    }
}

fn main() {
    env_logger::init();
    let matches = App::new("michat")
        .arg(
            Arg::with_name("bind")
                .short("l")
                .takes_value(true)
                .required(true),
        )
        .get_matches();

    let address = value_t_or_exit!(matches.value_of("bind"), std::net::SocketAddr);
    let listener = TcpListener::bind(&address).expect("bind");

    let mut event_loop = mio::Poll::new().expect("Create event loop");
    let mut service = MiChat::new();

    service
        .listen(&mut event_loop, listener)
        .expect("Starting listener");
    info!("running michat listener at: {:?}", address);
    service.run(&mut event_loop).expect("run");
}
<|endoftext|>


<commit_before>extern crate serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

#[cfg(not(test))] use std::io::stdio;
#[cfg(not(test))] use docopt::Docopt;
#[cfg(not(test))] use iota::{Editor, Input};
#[cfg(not(test))] static USAGE: &'static str = "
Usage: iota [<filename>]
       iota --help

Options:
    -h, --help     Show this message.
";

#[deriving(Decodable, Show)]
struct Args {
    arg_filename: Option<String>,
    flag_help: bool,
}

#[cfg(not(test))]
fn main() {
    struct RustBoxGuard;

    impl Drop for RustBoxGuard {
        fn drop(&mut self) { rustbox::shutdown() }
    }

    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    let source = if stdio::stdin_raw().isatty() {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdio::stdin())
    };

    rustbox::init();
    let _guard = RustBoxGuard; // Ensure that RustBox gets shut down on abnormal termination.
    let mut editor = Editor::new(source);
    editor.start();
}
<commit_msg>Print out string error messages after panic!<commit_after>extern crate serialize;
extern crate rustrt;
extern crate rustbox;
extern crate docopt;
extern crate iota;

#[cfg(not(test))] use std::any::{Any, AnyRefExt};
#[cfg(not(test))] use std::io::stdio;
#[cfg(not(test))] use std::task;
#[cfg(not(test))] use rustrt::unwind;
#[cfg(not(test))] use docopt::Docopt;
#[cfg(not(test))] use iota::{Editor, Input};
#[cfg(not(test))] static USAGE: &'static str = "
Usage: iota [<filename>]
       iota --help

Options:
    -h, --help     Show this message.
";

#[deriving(Decodable, Show)]
struct Args {
    arg_filename: Option<String>,
    flag_help: bool,
}

#[cfg(not(test))]
fn main() {
    struct RustBoxGuard;

    impl Drop for RustBoxGuard {
        fn drop(&mut self) {
            if !task::failing() {
                rustbox::shutdown();
            }
        }
    }

    fn rustbox_panic(msg: &(Any + Send), file: &'static str, line: uint) {
        rustbox::shutdown();
        let msg = match msg.downcast_ref::<String>() {
            Some(m) => m.clone(),
            None => match msg.downcast_ref::<&str>() {
                Some(m) => m.to_string(),
                None => "".to_string()
            }
        };
        let _ = writeln!(&mut stdio::stderr(), "panic at {}, line {}: {}", file, line, msg);
    }

    unsafe { unwind::register(rustbox_panic); }

    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    let source = if stdio::stdin_raw().isatty() {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdio::stdin())
    };

    rustbox::init();
    let _guard = RustBoxGuard; // Ensure that RustBox gets shut down on abnormal termination.
    let mut editor = Editor::new(source);
    editor.start();
}
<|endoftext|>


<commit_before>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262_144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524_288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2_400_000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;
    let deviation: f32 = env::args()
        .nth(4)
        .expect("Please specify the deviation.")
        .parse::<f32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr =
            RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes.as_slice()).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt = windowed_sinc(
            bandwidth as f32,
            SDR_SAMPLE_RATE as f32,
            16,
            &hamming,
        );
        let taps_audio = windowed_sinc(
            bandwidth as f32 / dec_rate_filt as f32,
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            16,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(&iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(&iq_vec, prev, deviation);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(&demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => {
                    match available {
                        pa::StreamAvailable::Frames(frames) => frames as u32,
                        pa::StreamAvailable::InputOverflowed => {
                            return Err(Box::new(PAError::InputOverflowed))
                        }
                        pa::StreamAvailable::OutputUnderflowed => {
                            return Err(Box::new(PAError::OutputUnderflowed))
                        }
                    }
                }
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream.write(
            buffer_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            },
        )?;
    }
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

/// Decimates a signal by an integer factor.
///
/// # Arguments
///
/// * `signal` - The signal to decimate
/// * `dec_rate` - The decimation factor
///
fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

/// Converts samples from the SDR into complex IQ pairs.
///
/// # Arguments
///
/// * `bytes` - The unsigned bytes from the SDR.
///
fn samps_to_cmplx(bytes: &[u8]) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

/// Performs FM demodulation on a complex signal.
///
/// # Arguments
///
/// * `iq` - The IQ samples to demodulate.
/// * `prev` - The previous sample from the previous demodulation.
/// * `deviation` - The maximum frequency deviation in Hz.
///
fn demod_fm(
    iq: &[Complex<f32>],
    prev: Complex<f32>,
    deviation: f32,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev;
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * deviation);

    for samp in iq {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

/// Filters a Complex vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The complex samples to filter
/// * `taps` - The taps of the filter
///
fn filter<T: Copy + Num + Zero>(
    samples: &[Complex<T>],
    taps: &[T],
) -> Vec<Complex<T>> {

    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

/// Filters a real vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The real samples to filter
/// * `taps` - The taps of the filter
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &[T],
    taps: &[T],
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

/// Generates a vector containing the taps for a Hamming window.
///
/// # Arguments
///
/// * `ntaps` - The number of taps to generate for the filter
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

/// Generates filter taps for a sinc filter with a windowing function.
///
/// # Arguments
///
/// * `cutoff_freq` - The cutoff frequency in Hertz
/// * `sample_rate` - The sample frequency in Hertz
/// * `ntaps` - The number of taps to generate for the window
/// * `window` - The windowing function used to generate the taps for the window
///
fn windowed_sinc(
    cutoff_freq: f32,
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    // Convert the frequency to radians and make it a ratio of the sample rate.
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<commit_msg>Rustfmt updates<commit_after>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262_144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524_288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2_400_000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;
    let deviation: f32 = env::args()
        .nth(4)
        .expect("Please specify the deviation.")
        .parse::<f32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr =
            RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes.as_slice()).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt = windowed_sinc(bandwidth as f32,
                                      SDR_SAMPLE_RATE as f32,
                                      16,
                                      &hamming);
        let taps_audio = windowed_sinc(bandwidth as f32 / dec_rate_filt as f32,
                                       SDR_SAMPLE_RATE as f32 /
                                       dec_rate_filt as f32,
                                       16,
                                       &hamming);

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(&iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(&iq_vec, prev, deviation);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(&demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings =
        try!(audio.default_output_stream_settings(CHANNELS,
                                                  AUDIO_SAMPLE_RATE as f64,
                                                  AUDIO_BUF_SIZE as u32));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => {
                    match available {
                        pa::StreamAvailable::Frames(frames) => frames as u32,
                        pa::StreamAvailable::InputOverflowed => {
                            return Err(Box::new(PAError::InputOverflowed))
                        }
                        pa::StreamAvailable::OutputUnderflowed => {
                            return Err(Box::new(PAError::OutputUnderflowed))
                        }
                    }
                }
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream
            .write(buffer_frames, |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            })?;
    }
}

fn init_sdr(sdr_index: i32,
            fm_freq: u32,
            bandwidth: u32)
            -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

/// Decimates a signal by an integer factor.
///
/// # Arguments
///
/// * `signal` - The signal to decimate
/// * `dec_rate` - The decimation factor
///
fn decimate<T: Copy>(signal: &[T], dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

/// Converts samples from the SDR into complex IQ pairs.
///
/// # Arguments
///
/// * `bytes` - The unsigned bytes from the SDR.
///
fn samps_to_cmplx(bytes: &[u8]) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new((iq[0] as f32 - 127.0) / 127.0,
                                    (iq[1] as f32 - 127.0) / 127.0);
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

/// Performs FM demodulation on a complex signal.
///
/// # Arguments
///
/// * `iq` - The IQ samples to demodulate.
/// * `prev` - The previous sample from the previous demodulation.
/// * `deviation` - The maximum frequency deviation in Hz.
///
fn demod_fm(iq: &[Complex<f32>],
            prev: Complex<f32>,
            deviation: f32)
            -> (Vec<f32>, Complex<f32>) {

    let mut p = prev;
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * deviation);

    for samp in iq {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

/// Filters a Complex vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The complex samples to filter
/// * `taps` - The taps of the filter
///
fn filter<T: Copy + Num + Zero>(samples: &[Complex<T>],
                                taps: &[T])
                                -> Vec<Complex<T>> {

    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

/// Filters a real vector and returns a new vector.
///
/// # Arguments
///
/// * `samples` - The real samples to filter
/// * `taps` - The taps of the filter
///
fn filter_real<T: Copy + Num + Zero>(samples: &[T], taps: &[T]) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> = Vec::with_capacity(samples.len() - taps.len() +
                                                    1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

/// Generates a vector containing the taps for a Hamming window.
///
/// # Arguments
///
/// * `ntaps` - The number of taps to generate for the filter
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

/// Generates filter taps for a sinc filter with a windowing function.
///
/// # Arguments
///
/// * `cutoff_freq` - The cutoff frequency in Hertz
/// * `sample_rate` - The sample frequency in Hertz
/// * `ntaps` - The number of taps to generate for the window
/// * `window` - The windowing function used to generate the taps for the window
///
fn windowed_sinc(cutoff_freq: f32,
                 sample_rate: f32,
                 ntaps: usize,
                 window: &Fn(usize) -> Vec<f32>)
                 -> Vec<f32> {
    // Convert the frequency to radians and make it a ratio of the sample rate.
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                     win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<|endoftext|>


<commit_before>#![feature(decode_utf8)]
#![feature(io)]

extern crate argparse;
extern crate bit_set;
extern crate byteorder;
extern crate compress;
extern crate libc;

use std::fs;
use std::io;
use std::mem;
use std::path;
use std::slice;

use argparse::{Store, StoreTrue};

use bit_set::BitSet;

use byteorder::{BigEndian, ReadBytesExt};

use compress::lz4;

use libc::c_void;

//magic:
use std::io::Read;
use std::io::Seek;
use std::os::unix::io::AsRawFd;

type CharResult = Result<char, io::CharsError>;

static TRI_MAX: usize = 64 * 64 * 64;

fn simplify(wut: char) -> u8 {
    let c = match wut {
        'a' ... 'z' => (wut as u8 - 'a' as u8 + 'A' as u8) as char,
        _ => wut,
    };

    if c > 128 as char {
        if c.is_whitespace() {
            return 2;
        }
        if c.is_control() {
            return 0;
        }
        return 63;
    }

    let sym_end = 33u8;
    let letters = 21u8;

    match c {
        '\r' | '\n' => 1,
        '\t' | '\x0c' | '\x0b' | ' ' => 2,
        '!' => 3,
        '"' | '\'' | '`' => 4,
        '$' => 5,
        '%' => 6,
        '&' => 7,
        '(' ... '@' => 8 + (c as u8 - '(' as u8),
        'A' ... 'I' => sym_end + (c as u8 - 'A' as u8),
        'J' | 'K' => sym_end + letters,
        'L' ... 'P' => sym_end + (c as u8 - 'A' as u8) - 2,
        'Q' => sym_end + letters,
        'R' ... 'W' => sym_end + (c as u8 - 'A' as u8) - 3,
        'X' | 'Z' => sym_end + letters,
        'Y' => sym_end + letters - 1,
        '[' => 55,
        '\\' => 56,
        ']'=> 57,
        '^' | '~' | '#' => 58,
        '_' => 59,
        '{' ... '}' => 60 + (c as u8 - '{' as u8),
        _ => 0,
    }
}

fn explain(wut: u8) -> char {
    match wut {
        0 => 'X',
        1 => 'N',
        2 => ' ',
        3 => '!',
        4 => '"',
        5 => '$',
        6 => '%',
        7 => '&',
        8 ... 32 => (wut - 8 + '(' as u8) as char,
        33 ... 41 => (wut - 33 + 'a' as u8) as char,
        42 ... 46 => (wut - 42 + 'l' as u8) as char,
        47 ... 52 => (wut - 47 + 'r' as u8) as char,
        53 => 'y',
        54 => 'X',
        55 => '[',
        56 => '\\',
        57 => ']',
        58 => '#',
        59 => '_',
        60 ... 62 => (wut - 60 + '{' as u8) as char,
        63 => 'U',
        _ => 'D',
    }
}

fn unpack(wut: usize) -> String {
    let mut ret = String::with_capacity(3);
    ret.push(explain((wut / 64 / 64 % 64) as u8));
    ret.push(explain((wut / 64 % 64) as u8));
    ret.push(explain((wut % 64) as u8));
    return ret;
}

fn trigrams_for<T: Iterator<Item=CharResult>>(input: T) -> Result<BitSet, String> {
    let mut line: u64 = 1;
    let mut prev: [u8; 3] = [0; 3];
    let mut ret: BitSet = BitSet::with_capacity(64 * 64 * 64);

    for (off, maybe_char) in input.enumerate() {
        let c = try!(maybe_char.map_err(|e| {
            format!("line {}: file char {}: failed: {}", line, off, e)
        }));
        if '\n' == c {
            line += 1;
        }
        if '\0' == c {
            return Err(format!("line {}: null found: not a text file", line));
        }
        prev[0] = prev[1];
        prev[1] = prev[2];
        prev[2] = simplify(c);
        let tri: usize = 64 * 64 * prev[0] as usize + 64 * prev[1] as usize + prev[2] as usize;
        ret.insert(tri);
    }
    return Ok(ret);
}

struct Mapped<'a, T: 'a> {
    file: fs::File,
    map: *mut c_void,
    data: &'a mut [T],
}

impl <'a, T: 'a> Mapped<'a, T> {
    fn fixed_len<P>(path: P, len: usize) -> io::Result<Mapped<'a, T>>
        where P: AsRef<path::Path> {
        let file = fs::OpenOptions::new().read(true).write(true).create(true).open(path)?;
        file.set_len(mem::size_of::<T>() as u64 * len as u64)?;
        let map: *mut c_void = unsafe {
            libc::mmap(0 as *mut c_void,
                       len * mem::size_of::<T>(),
                       libc::PROT_READ | libc::PROT_WRITE,
                       libc::MAP_SHARED,
                       file.as_raw_fd(),
                       0)
        };

        if libc::MAP_FAILED == map {
            return Err(io::Error::last_os_error());
        }

        let data = unsafe { slice::from_raw_parts_mut(map as *mut T, len) };
        Ok(Mapped { file, map, data })
    }

    fn remap(&mut self, len: usize) -> io::Result<()> {
        self.file.set_len(mem::size_of::<T>() as u64 * len as u64)?;
        let new_map = unsafe {
            libc::mremap(self.map,
                         self.data.len() * mem::size_of::<T>(),
                         len * mem::size_of::<T>(),
                         libc::MREMAP_MAYMOVE)
        };

        if libc::MAP_FAILED == new_map {
            return Err(io::Error::last_os_error());
        }

        self.data = unsafe { slice::from_raw_parts_mut(new_map as *mut T, len) };
        self.map = new_map;
        Ok(())
    }
}

impl <'a, T: 'a> Drop for Mapped<'a, T> {
    fn drop(&mut self) {
        unsafe {
            assert_eq!(0, libc::munmap(self.map, self.data.len() * mem::size_of::<T>()));
        }
    }
}

struct Index<'a> {
    idx: Mapped<'a, u32>,
    pages: Mapped<'a, u64>,
    free_page: usize,
    page_size: usize,
}

impl<'a> Index<'a> {
    fn new() -> io::Result<Index<'a>> {
        let idx: Mapped<u32> = Mapped::fixed_len("idx", TRI_MAX).unwrap();

        let page_size: usize = 1024;

        let pages_len: usize = match fs::metadata("pages") {
            Ok(m) => {
                let proposed: u64 = m.len() / mem::size_of::<u64>() as u64;
                assert!(proposed < usize::max_value() as u64);
                proposed as usize
            },
            Err(e) => if e.kind() == io::ErrorKind::NotFound {
                2 * page_size
            } else {
                panic!("couldn't get info on pages file: {}", e)
            }
        };

        let pages: Mapped<u64> = Mapped::fixed_len("pages", pages_len)?;
        let mut free_page: usize = pages.data.len() / page_size;

        loop {
            if 0 != pages.data[(free_page - 1) * page_size] {
                break;
            }
            if 1 == free_page {
                break;
            }
            free_page -= 1;
        }

        Ok(Index { idx, pages, free_page, page_size })
    }

    fn page_for(&mut self, trigram: u32) -> io::Result<usize> {
        assert!(trigram < TRI_MAX as u32);

        let page = self.idx.data[trigram as usize] as usize;
        if 0 != page {
            return Ok(page);
        }

        let found_page = self.next_page()?;
        self.idx.data[trigram as usize] = found_page as u32;
        Ok(found_page)
    }

    fn next_page(&mut self) -> io::Result<usize> {
        let ret = self.free_page;
        self.free_page += 1;
        if self.free_page >= self.pages.data.len() / self.page_size {
            let old_len = self.pages.data.len();
            self.pages.remap(old_len + 100 * self.page_size)?;
        }

        Ok(ret)
    }

    fn append(&mut self, trigram: u32, document: u64) -> io::Result<()> {
        let mut page = self.page_for(trigram)?;
        let mut header_loc;
        let mut header;
        loop {
            header_loc = page * self.page_size;
            header = self.pages.data[header_loc];
            if header == (self.page_size - 1) as u64 {
                page = self.next_page()?;
                self.pages.data[header_loc] = page as u64 + self.page_size as u64;
                header = 0;
                header_loc = page * self.page_size;
                break;
            } else if header >= self.page_size as u64 {
                page = header as usize - self.page_size;
            } else {
                break;
            }
        }
        self.pages.data[header_loc] += 1;
        self.pages.data[page * self.page_size + 1 + header as usize] = document;
        Ok(())
    }

    fn append_trigrams(&mut self, trigrams: BitSet, document: u64) -> io::Result<()> {
        for found in trigrams.iter() {
            self.append(found as u32, document)?;
        }
        Ok(())
    }
}

fn round_up(x: u64) -> u64 {
    let mut ret = x;
    loop {
        if ret % 16 == 0 {
            return ret;
        }
        ret += 1;
    }
}

fn eat_chunk(mut fh: &mut fs::File) -> io::Result<BitSet> {
    let end = fh.read_u64::<BigEndian>()?;
    let extra_len = fh.read_u64::<BigEndian>()?;
    let start = fh.seek(io::SeekFrom::Current(extra_len as i64))?;
    let ret = {
        let decoder = lz4::Decoder::new(&mut fh);
        let range = decoder.bytes();
        let exploding = range.map(|x| x.unwrap());
        let decoder = std::char::decode_utf8(exploding);
        let errors = decoder.map(|x| x.map_err(|_| io::CharsError::NotUtf8));
        trigrams_for(errors).map_err(|msg| io::Error::new(io::ErrorKind::Other, msg))
    };
    let next = round_up(start + end - extra_len - 16);
    fh.seek(io::SeekFrom::Start(next))?;
    ret
}

fn main() {
    let mut from: String = "".to_string();
    let mut simple = false;
    let mut addendum: u64 = 0;
    {
        let mut ap = argparse::ArgumentParser::new();
        ap.set_description("totally not a load of tools glued together");
        ap.refer(&mut from)
                .required()
                .add_option(&["-f", "--input-file"], Store,
                            "pack file to read");
        ap.refer(&mut addendum)
                .add_option(&["-i", "--addendum"], Store,
                            "number to add to file offset");
        ap.refer(&mut simple)
                .add_option(&["--simple"], StoreTrue,
                            "not a pack, just a normal decompressed file");
        ap.parse_args_or_exit();
    }

    let mut idx = Index::new().unwrap();

    let mut fh = fs::File::open(from).expect("input file must exist and be readable");
    if simple {
        let trigrams = trigrams_for(fh.chars()).expect("trigramming must work");
        idx.append_trigrams(trigrams, addendum).unwrap();
        return;
    }

    fh.seek(io::SeekFrom::Start(16)).unwrap();
    loop {

        let document = fh.seek(io::SeekFrom::Current(0)).unwrap() + addendum;
        let trigrams = eat_chunk(&mut fh).unwrap();
        idx.append_trigrams(trigrams, document).unwrap();
    }
}
<commit_msg>handle errors in the pack file by ignoring the documents<commit_after>#![feature(decode_utf8)]
#![feature(io)]

extern crate argparse;
extern crate bit_set;
extern crate byteorder;
extern crate compress;
extern crate libc;

use std::fs;
use std::io;
use std::mem;
use std::path;
use std::slice;

use argparse::{Store, StoreTrue};

use bit_set::BitSet;

use byteorder::{BigEndian, ReadBytesExt};

use compress::lz4;

use libc::c_void;

//magic:
use std::io::Read;
use std::io::Seek;
use std::os::unix::io::AsRawFd;

type CharResult = Result<char, io::CharsError>;

static TRI_MAX: usize = 64 * 64 * 64;

fn simplify(wut: char) -> u8 {
    let c = match wut {
        'a' ... 'z' => (wut as u8 - 'a' as u8 + 'A' as u8) as char,
        _ => wut,
    };

    if c > 128 as char {
        if c.is_whitespace() {
            return 2;
        }
        if c.is_control() {
            return 0;
        }
        return 63;
    }

    let sym_end = 33u8;
    let letters = 21u8;

    match c {
        '\r' | '\n' => 1,
        '\t' | '\x0c' | '\x0b' | ' ' => 2,
        '!' => 3,
        '"' | '\'' | '`' => 4,
        '$' => 5,
        '%' => 6,
        '&' => 7,
        '(' ... '@' => 8 + (c as u8 - '(' as u8),
        'A' ... 'I' => sym_end + (c as u8 - 'A' as u8),
        'J' | 'K' => sym_end + letters,
        'L' ... 'P' => sym_end + (c as u8 - 'A' as u8) - 2,
        'Q' => sym_end + letters,
        'R' ... 'W' => sym_end + (c as u8 - 'A' as u8) - 3,
        'X' | 'Z' => sym_end + letters,
        'Y' => sym_end + letters - 1,
        '[' => 55,
        '\\' => 56,
        ']'=> 57,
        '^' | '~' | '#' => 58,
        '_' => 59,
        '{' ... '}' => 60 + (c as u8 - '{' as u8),
        _ => 0,
    }
}

fn explain(wut: u8) -> char {
    match wut {
        0 => 'X',
        1 => 'N',
        2 => ' ',
        3 => '!',
        4 => '"',
        5 => '$',
        6 => '%',
        7 => '&',
        8 ... 32 => (wut - 8 + '(' as u8) as char,
        33 ... 41 => (wut - 33 + 'a' as u8) as char,
        42 ... 46 => (wut - 42 + 'l' as u8) as char,
        47 ... 52 => (wut - 47 + 'r' as u8) as char,
        53 => 'y',
        54 => 'X',
        55 => '[',
        56 => '\\',
        57 => ']',
        58 => '#',
        59 => '_',
        60 ... 62 => (wut - 60 + '{' as u8) as char,
        63 => 'U',
        _ => 'D',
    }
}

fn unpack(wut: usize) -> String {
    let mut ret = String::with_capacity(3);
    ret.push(explain((wut / 64 / 64 % 64) as u8));
    ret.push(explain((wut / 64 % 64) as u8));
    ret.push(explain((wut % 64) as u8));
    return ret;
}

fn trigrams_for<T: Iterator<Item=CharResult>>(input: T) -> Result<BitSet, String> {
    let mut line: u64 = 1;
    let mut prev: [u8; 3] = [0; 3];
    let mut ret: BitSet = BitSet::with_capacity(64 * 64 * 64);

    for (off, maybe_char) in input.enumerate() {
        let c = try!(maybe_char.map_err(|e| {
            format!("line {}: file char {}: failed: {}", line, off, e)
        }));
        if '\n' == c {
            line += 1;
        }
        if '\0' == c {
            return Err(format!("line {}: null found: not a text file", line));
        }
        prev[0] = prev[1];
        prev[1] = prev[2];
        prev[2] = simplify(c);
        let tri: usize = 64 * 64 * prev[0] as usize + 64 * prev[1] as usize + prev[2] as usize;
        ret.insert(tri);
    }
    return Ok(ret);
}

struct Mapped<'a, T: 'a> {
    file: fs::File,
    map: *mut c_void,
    data: &'a mut [T],
}

impl <'a, T: 'a> Mapped<'a, T> {
    fn fixed_len<P>(path: P, len: usize) -> io::Result<Mapped<'a, T>>
        where P: AsRef<path::Path> {
        let file = fs::OpenOptions::new().read(true).write(true).create(true).open(path)?;
        file.set_len(mem::size_of::<T>() as u64 * len as u64)?;
        let map: *mut c_void = unsafe {
            libc::mmap(0 as *mut c_void,
                       len * mem::size_of::<T>(),
                       libc::PROT_READ | libc::PROT_WRITE,
                       libc::MAP_SHARED,
                       file.as_raw_fd(),
                       0)
        };

        if libc::MAP_FAILED == map {
            return Err(io::Error::last_os_error());
        }

        let data = unsafe { slice::from_raw_parts_mut(map as *mut T, len) };
        Ok(Mapped { file, map, data })
    }

    fn remap(&mut self, len: usize) -> io::Result<()> {
        self.file.set_len(mem::size_of::<T>() as u64 * len as u64)?;
        let new_map = unsafe {
            libc::mremap(self.map,
                         self.data.len() * mem::size_of::<T>(),
                         len * mem::size_of::<T>(),
                         libc::MREMAP_MAYMOVE)
        };

        if libc::MAP_FAILED == new_map {
            return Err(io::Error::last_os_error());
        }

        self.data = unsafe { slice::from_raw_parts_mut(new_map as *mut T, len) };
        self.map = new_map;
        Ok(())
    }
}

impl <'a, T: 'a> Drop for Mapped<'a, T> {
    fn drop(&mut self) {
        unsafe {
            assert_eq!(0, libc::munmap(self.map, self.data.len() * mem::size_of::<T>()));
        }
    }
}

struct Index<'a> {
    idx: Mapped<'a, u32>,
    pages: Mapped<'a, u64>,
    free_page: usize,
    page_size: usize,
}

impl<'a> Index<'a> {
    fn new() -> io::Result<Index<'a>> {
        let idx: Mapped<u32> = Mapped::fixed_len("idx", TRI_MAX).unwrap();

        let page_size: usize = 1024;

        let pages_len: usize = match fs::metadata("pages") {
            Ok(m) => {
                let proposed: u64 = m.len() / mem::size_of::<u64>() as u64;
                assert!(proposed < usize::max_value() as u64);
                proposed as usize
            },
            Err(e) => if e.kind() == io::ErrorKind::NotFound {
                2 * page_size
            } else {
                panic!("couldn't get info on pages file: {}", e)
            }
        };

        let pages: Mapped<u64> = Mapped::fixed_len("pages", pages_len)?;
        let mut free_page: usize = pages.data.len() / page_size;

        loop {
            if 0 != pages.data[(free_page - 1) * page_size] {
                break;
            }
            if 1 == free_page {
                break;
            }
            free_page -= 1;
        }

        Ok(Index { idx, pages, free_page, page_size })
    }

    fn page_for(&mut self, trigram: u32) -> io::Result<usize> {
        assert!(trigram < TRI_MAX as u32);

        let page = self.idx.data[trigram as usize] as usize;
        if 0 != page {
            return Ok(page);
        }

        let found_page = self.next_page()?;
        self.idx.data[trigram as usize] = found_page as u32;
        Ok(found_page)
    }

    fn next_page(&mut self) -> io::Result<usize> {
        let ret = self.free_page;
        self.free_page += 1;
        if self.free_page >= self.pages.data.len() / self.page_size {
            let old_len = self.pages.data.len();
            self.pages.remap(old_len + 100 * self.page_size)?;
        }

        Ok(ret)
    }

    fn append(&mut self, trigram: u32, document: u64) -> io::Result<()> {
        let mut page = self.page_for(trigram)?;
        let mut header_loc;
        let mut header;
        loop {
            header_loc = page * self.page_size;
            header = self.pages.data[header_loc];
            if header == (self.page_size - 1) as u64 {
                page = self.next_page()?;
                self.pages.data[header_loc] = page as u64 + self.page_size as u64;
                header = 0;
                header_loc = page * self.page_size;
                break;
            } else if header >= self.page_size as u64 {
                page = header as usize - self.page_size;
            } else {
                break;
            }
        }
        self.pages.data[header_loc] += 1;
        self.pages.data[header_loc + 1 + header as usize] = document;
        Ok(())
    }

    fn append_trigrams(&mut self, trigrams: BitSet, document: u64) -> io::Result<()> {
        for found in trigrams.iter() {
            self.append(found as u32, document)?;
        }
        Ok(())
    }
}

fn round_up(x: u64) -> u64 {
    let mut ret = x;
    loop {
        if ret % 16 == 0 {
            return ret;
        }
        ret += 1;
    }
}

fn eat_chunk(mut fh: &mut fs::File) -> io::Result<BitSet> {
    let end = fh.read_u64::<BigEndian>()?;
    let extra_len = fh.read_u64::<BigEndian>()?;
    let start = fh.seek(io::SeekFrom::Current(extra_len as i64))?;
    let ret = {
        let decoder = lz4::Decoder::new(&mut fh);
        let range = decoder.bytes();
        let exploding = range.map(|x| x.unwrap());
        let decoder = std::char::decode_utf8(exploding);
        let errors = decoder.map(|x| x.map_err(|_| io::CharsError::NotUtf8));
        trigrams_for(errors).map_err(|msg| io::Error::new(io::ErrorKind::Other, msg))
    };
    let next = round_up(start + end - extra_len - 16);
    fh.seek(io::SeekFrom::Start(next))?;
    ret
}

fn main() {
    let mut from: String = "".to_string();
    let mut simple = false;
    let mut addendum: u64 = 0;
    {
        let mut ap = argparse::ArgumentParser::new();
        ap.set_description("totally not a load of tools glued together");
        ap.refer(&mut from)
                .required()
                .add_option(&["-f", "--input-file"], Store,
                            "pack file to read");
        ap.refer(&mut addendum)
                .add_option(&["-i", "--addendum"], Store,
                            "number to add to file offset");
        ap.refer(&mut simple)
                .add_option(&["--simple"], StoreTrue,
                            "not a pack, just a normal decompressed file");
        ap.parse_args_or_exit();
    }

    let mut idx = Index::new().unwrap();

    let mut fh = fs::File::open(from).expect("input file must exist and be readable");
    if simple {
        let trigrams = trigrams_for(fh.chars()).expect("trigramming must work");
        idx.append_trigrams(trigrams, addendum).unwrap();
        return;
    }

    fh.seek(io::SeekFrom::Start(16)).unwrap();
    loop {
        let document = fh.seek(io::SeekFrom::Current(0)).unwrap() + addendum;
        match eat_chunk(&mut fh) {
            Ok(trigrams) => idx.append_trigrams(trigrams, document).unwrap(),
            Err(e) => {
                if e.kind() == io::ErrorKind::UnexpectedEof {
                    break;
                }
                println!("document {}: trigramming failed: {}", document, e)
            },
        };
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate hyper;

use rustc_serialize::{json};
#[macro_use] extern crate nickel;

use nickel::status::StatusCode;
use nickel::{Nickel, HttpRouter, MediaType};

#[derive(RustcDecodable, RustcEncodable)]
struct Todo {
  status: i32,
  title: String,
}

fn main() {
  let mut server = Nickel::new();
  let mut router = Nickel::router();

  // index
  router.get("/api/todos", middleware! { |_, mut _res|
    let mut v: Vec<Todo> = vec![];
    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    v.push(todo1);
    let todo2 = Todo{
      status: 1,
      title: "Movie".to_string(),
    };
    v.push(todo2);

    let json_obj = json::encode(&v).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // detail
  router.get("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("id: {:?}", id);

    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    let json_obj = json::encode(&todo1).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  server.utilize(router);
  server.listen("127.0.0.1:6767");
}
<commit_msg>add delete API<commit_after>extern crate rustc_serialize;
extern crate hyper;

use rustc_serialize::json;
use rustc_serialize::json::Json;
#[macro_use] extern crate nickel;

use nickel::status::StatusCode;
use nickel::{Nickel, HttpRouter, MediaType};

#[derive(RustcDecodable, RustcEncodable)]
struct Todo {
  status: i32,
  title: String,
}

fn main() {
  let mut server = Nickel::new();
  let mut router = Nickel::router();

  // index
  router.get("/api/todos", middleware! { |_, mut _res|
    let mut v: Vec<Todo> = vec![];
    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    v.push(todo1);
    let todo2 = Todo{
      status: 1,
      title: "Movie".to_string(),
    };
    v.push(todo2);

    let json_obj = json::encode(&v).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // detail
  router.get("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("id: {:?}", id);

    let todo1 = Todo{
      status: 0,
      title: "Shopping".to_string(),
    };
    let json_obj = json::encode(&todo1).unwrap();
    _res.set(MediaType::Json);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  // delete
  router.delete("/api/todos/:id", middleware! { |_req, mut _res|
    let id = _req.param("id");
    println!("delete id: {:?}", id);

    let json_obj = Json::from_str("{}").unwrap();
    _res.set(MediaType::Json);
    //_res.set(StatusCode::NoContent);
    _res.set(StatusCode::Ok);
    return _res.send(json_obj);
  });

  server.utilize(router);
  server.listen("127.0.0.1:6767");
}
<|endoftext|>


<commit_before>extern crate xml;
extern crate rustc;

use std::os;

use std::io::{File, BufferedReader};
use std::fmt;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread::Thread;
use std::io::timer::sleep;
use std::time::duration::Duration;

use rustc::middle::graph::{NodeIndex, Graph};

use xml::reader::EventReader;
use xml::reader::events::XmlEvent;

fn main() {
	println!("XGConsole:");
	for arg in parse_command_line(os::args()).iter() {
		println!("  {}", arg);
	}

	let mut path = Path::new(&os::args()[0]).dir_path();
	path.push("../tests/graph-parser.xml");
	println!("Example path: {}", path.display());
	xg_parse(&path);

	let (tx_result, rx_result): (Sender<String>, Receiver<String>) = channel();
	let (tx_task, rx_task): (Sender<String>, Receiver<String>) = channel();
	let mutex_rx_task = Arc::new(Mutex::new(rx_task));

	for cpu_id in range(0, std::os::num_cpus()) {
		let local_rx_task = mutex_rx_task.clone();
		let local_tx_result = tx_result .clone();
				Thread::spawn(move || {
				loop {
					let message: String;
					{
						match local_rx_task.lock().recv_opt() {
								Ok(v) => {message = v;}
								Err(_) => {break;}
							}
					}
					println!("{}: {}", cpu_id, message);
					sleep(Duration::milliseconds(100));
					local_tx_result.send(format!("Done {}", message));
				}
				println!("{}: done", cpu_id);
			}).detach();
	}
	free(tx_result);

	for task_id in range (0i, 50i) {
			tx_task.send(format!("Task {}", task_id));
	}
	free(tx_task);

	for message in rx_result.iter() {
		println!("B: {}", message);
	}
	println!("done");
}

fn free<T>(_:T) {
}

fn parse_command_line(args: Vec<String>) -> Vec<String> {
	let mut result: Vec<String> = Vec::new();
	for arg in args.slice(1, args.len()).iter() {
			result.push(arg.clone());
	}
	result
}

struct BuildTask {
working_dir: String,
}

struct XgTask {
id: Option<String>,
title: Option<String>,
tool: String,
working_dir: String,
depends_on: Vec<String>,
}

impl fmt::Show for XgTask {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, title={}, tool={}, working_dir={}, depends_on={}", self .id, self .title, self .tool, self .working_dir, self .depends_on)
}
}

struct XgTool {
id: String,
path: String,
params: String,
}

impl fmt::Show for XgTool {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, path={}", self .id, self .path)
}
}

fn xg_parse(path: &Path) -> Result<Graph<BuildTask, ()>, String> {
	let file = File::open(path).unwrap();
	let reader = BufferedReader::new(file);

	let mut parser = EventReader::new(reader);
	let mut tasks:Vec<XgTask> = vec![];
	let mut tools:HashMap<String, XgTool> = HashMap::new();
	for e in parser.events() {
		match e {
				XmlEvent::StartElement {name, attributes, ..} => {
				match name.local_name.as_slice() {
						"Task" =>
						{
							match xg_parse_task(&attributes) {
									Ok(task) =>
									{
											tasks.push(task);
									}
									Err(msg) =>
									{
										panic!(msg);
									}
								};
						}
						"Tool" =>
						{
							match xg_parse_tool(&attributes) {
									Ok(tool) =>
									{
											tools.insert(tool.id.to_string(), tool);
									}
									Err(msg) =>
									{
										panic!(msg);
									}
								};
						}
						_ => {}
					}
			}
				XmlEvent::EndElement{..} => {
			}
				_ => {
			}
			}
	}
	xg_parse_create_graph(&tasks)
}

fn xg_parse_create_graph(tasks:&Vec<XgTask>) -> Result<Graph<BuildTask, ()>, String> {
	let mut graph: Graph<BuildTask, ()> = Graph::new();
	let mut nodes: Vec<NodeIndex> = vec![];
	let mut task_refs: HashMap<&str, NodeIndex> = HashMap::new();
	for task in tasks.iter() {
		let node = graph.add_node(BuildTask {
		working_dir : task.working_dir.clone(),
		});
		match task.id {
				Some(ref v) => {
					task_refs.insert(v.as_slice(), node);
			}
				_ => {}
			}
		nodes.push(node);
	}
	for idx in range(0, nodes.len()) {
		let ref task = tasks[idx];
		let ref node = nodes[idx];
		for id in task.depends_on.iter() {
			let dep_node = task_refs.get(id.as_slice());
			match dep_node {
					Some(v) => {
						graph.add_edge(*node, *v, ());
				}
					_ => {
					return Err(format!("Can't find task for dependency with id: {}", id));
				}
				}
		}
	}
	Ok(graph)
}

fn map_attributes (attributes: &Vec<xml::attribute::OwnedAttribute>) -> HashMap< String, String> {
	let mut attrs: HashMap<String, String> = HashMap::new();
	for attr in attributes.iter() {
			attrs.insert(attr.name.local_name.clone(), attr.value.clone());
	}
	attrs
}

fn xg_parse_task (attributes: & Vec<xml::attribute::OwnedAttribute>)->Result<XgTask, String> {
	let mut attrs = map_attributes(attributes);
	// Tool
	let tool: String;
	match attrs.remove("Tool") {
			Some(v) => {tool = v;}
			_ => {return Err("Invalid task data: attribute @Tool not found.".to_string());}
		}
	// WorkingDir
	let working_dir: String;
	match attrs.remove("WorkingDir") {
			Some(v) => {working_dir = v;}
			_ => {return Err("Invalid task data: attribute @WorkingDir not found.".to_string());}
		}
	// DependsOn
	let mut depends_on : Vec<String> = vec![];
	match attrs.remove("DependsOn") {
			Some(v) =>
			{
				for item in v.split_str(";").collect::<Vec<&str>>().iter() {
						depends_on.push(item.to_string())
				}
			}
			_ =>
			{
			}
		};

		Ok(XgTask {
	id: attrs.remove("Name"),
	title: attrs.remove("Caption"),
	tool: tool,
	working_dir: working_dir,
	depends_on: depends_on,
	})
}
fn xg_parse_tool (attributes: &Vec<xml::attribute::OwnedAttribute>)->Result<XgTool, String> {
	let mut attrs = map_attributes(attributes);
	// Name
	let id: String;
	match attrs.remove("Name") {
			Some(v) => {id = v;}
			_ => {return Err("Invalid task data: attribute @Name not found.".to_string());}
		}
	// Path
	let path: String;
	match attrs.remove("Path") {
			Some(v) => {path = v;}
			_ => {return Err("Invalid task data: attribute @Name not found.".to_string());}
		}

	Ok(XgTool {
	id: id,
	path: path,
	params: match attrs.remove("Params") {
			Some(v) => {v}
			_ => {"".to_string()}
		},
	})
}
<commit_msg>Executing build tasks.<commit_after>extern crate xml;
extern crate rustc;

use std::os;

use std::io::{File, BufferedReader};
use std::fmt;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread::Thread;
use std::io::timer::sleep;
use std::time::duration::Duration;

use rustc::middle::graph::{Graph, NodeIndex, Node, EdgeIndex, Edge};

use xml::reader::EventReader;
use xml::reader::events::XmlEvent;

struct TaskMessage {
index: NodeIndex,
task: BuildTask
}

impl fmt::Show for TaskMessage {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "index={}", self .index)
}
}

struct ResultMessage {
index: NodeIndex
}

impl fmt::Show for ResultMessage {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "index={}", self .index)
}
}

fn main() {
	println!("XGConsole:");
	for arg in parse_command_line(os::args()).iter() {
		println!("  {}", arg);
	}

	let (tx_result, rx_result): (Sender<ResultMessage>, Receiver<ResultMessage>) = channel();
	let (tx_task, rx_task): (Sender<TaskMessage>, Receiver<TaskMessage>) = channel();

	let mutex_rx_task = Arc::new(Mutex::new(rx_task));
	for cpu_id in range(0, std::os::num_cpus()) {
		let local_rx_task = mutex_rx_task.clone();
		let local_tx_result = tx_result .clone();
				Thread::spawn(move || {
				loop {
					match local_rx_task.lock().recv_opt() {
							Ok(message) => {
							println!("{}: {}", cpu_id, message);
								sleep(Duration::milliseconds(100));
								local_tx_result.send(ResultMessage{
							index: message.index,
							});
						}
							Err(_) => {break;}
						}
				}
				println!("{}: done", cpu_id);
			}).detach();
	}

	let mut path = Path::new(&os::args()[0]).dir_path();
	path.push("../tests/graph-parser.xml");
	println!("Example path: {}", path.display());
	match xg_parse(&path) {
			Ok(graph) => {
				execute_graph(&graph, tx_task, rx_result);
		}
			Err(msg) =>{panic! (msg);}
		}

	println!("done");
}

fn execute_graph(graph: &Graph<BuildTask, ()>, tx_task: Sender<TaskMessage>, rx_result: Receiver<ResultMessage>) {
	let mut completed:Vec<bool> = vec![];
		graph. each_node(|index: NodeIndex, node:&Node<BuildTask>|->bool {
		let mut has_edges = false;
			graph.each_outgoing_edge(index, |_:EdgeIndex, _:&Edge<()>| -> bool {
			has_edges = true;
			false
		});
		if !has_edges {
			println!("{}", index);
				tx_task.send(TaskMessage{
			index: index,
			task: node.data.clone(),
			});
		}
			completed.push(false);
		true
	});
	let mut count:uint = 0;
	for message in rx_result.iter() {
		assert!(!completed[message.index.node_id()]);
		completed[message.index.node_id()] = true;
			graph.each_incoming_edge(message.index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
			let source = edge.source();
			if !completed[source.node_id()] {
				println!("X: {}", source);
				let mut ready = true;
					graph.each_outgoing_edge(source, |_:EdgeIndex, deps:&Edge<()>| -> bool {
					if !completed[deps.target().node_id()]{
						ready = false;
						false
					} else {
						true
					}
				});
				if ready {
						tx_task.send(TaskMessage{
					index: source,
					task: graph.node(source).data.clone(),
					})  ;
						println!("R: {}", source);
				}
			}
			true
		});
		println!("R: {}", message);
		count += 1;
		if count ==completed.len() {
			break;
		}
	}
}

fn parse_command_line(args: Vec<String>) -> Vec<String> {
	let mut result: Vec<String> = Vec::new();
	for arg in args.slice(1, args.len()).iter() {
			result.push(arg.clone());
	}
	result
}

struct BuildTask {
working_dir: String,
}

impl Clone for BuildTask {
fn clone(& self) -> BuildTask {
	BuildTask {
	working_dir: self .working_dir.clone(),
	}
}
}

struct XgTask {
id: Option<String>,
title: Option<String>,
tool: String,
working_dir: String,
depends_on: Vec<String>,
}

impl fmt::Show for XgTask {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, title={}, tool={}, working_dir={}, depends_on={}", self .id, self .title, self .tool, self .working_dir, self .depends_on)
}
}

struct XgTool {
id: String,
path: String,
params: String,
}

impl fmt::Show for XgTool {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, path={}", self .id, self .path)
}
}

fn xg_parse(path: &Path) -> Result<Graph<BuildTask, ()>, String> {
	let file = File::open(path).unwrap();
	let reader = BufferedReader::new(file);

	let mut parser = EventReader::new(reader);
	let mut tasks:Vec<XgTask> = vec![];
	let mut tools:HashMap<String, XgTool> = HashMap::new();
	for e in parser.events() {
		match e {
				XmlEvent::StartElement {name, attributes, ..} => {
				match name.local_name.as_slice() {
						"Task" =>
						{
							match xg_parse_task(&attributes) {
									Ok(task) =>
									{
											tasks.push(task);
									}
									Err(msg) =>
									{
										panic!(msg);
									}
								};
						}
						"Tool" =>
						{
							match xg_parse_tool(&attributes) {
									Ok(tool) =>
									{
											tools.insert(tool.id.to_string(), tool);
									}
									Err(msg) =>
									{
										panic!(msg);
									}
								};
						}
						_ => {}
					}
			}
				XmlEvent::EndElement{..} => {
			}
				_ => {
			}
			}
	}
	xg_parse_create_graph(&tasks)
}

fn xg_parse_create_graph(tasks:&Vec<XgTask>) -> Result<Graph<BuildTask, ()>, String> {
	let mut graph: Graph<BuildTask, ()> = Graph::new();
	let mut nodes: Vec<NodeIndex> = vec![];
	let mut task_refs: HashMap<&str, NodeIndex> = HashMap::new();
	for task in tasks.iter() {
		let node = graph.add_node(BuildTask {
		working_dir : task.working_dir.clone(),
		});
		match task.id {
				Some(ref v) => {
					task_refs.insert(v.as_slice(), node);
			}
				_ => {}
			}
		nodes.push(node);
	}
	for idx in range(0, nodes.len()) {
		let ref task = tasks[idx];
		let ref node = nodes[idx];
		for id in task.depends_on.iter() {
			let dep_node = task_refs.get(id.as_slice());
			match dep_node {
					Some(v) => {
						graph.add_edge(*node, *v, ());
				}
					_ => {
					return Err(format!("Can't find task for dependency with id: {}", id));
				}
				}
		}
	}
	Ok(graph)
}

fn map_attributes (attributes: &Vec<xml::attribute::OwnedAttribute>) -> HashMap< String, String> {
	let mut attrs: HashMap<String, String> = HashMap::new();
	for attr in attributes.iter() {
			attrs.insert(attr.name.local_name.clone(), attr.value.clone());
	}
	attrs
}

fn xg_parse_task (attributes: & Vec<xml::attribute::OwnedAttribute>)->Result<XgTask, String> {
	let mut attrs = map_attributes(attributes);
	// Tool
	let tool: String;
	match attrs.remove("Tool") {
			Some(v) => {tool = v;}
			_ => {return Err("Invalid task data: attribute @Tool not found.".to_string());}
		}
	// WorkingDir
	let working_dir: String;
	match attrs.remove("WorkingDir") {
			Some(v) => {working_dir = v;}
			_ => {return Err("Invalid task data: attribute @WorkingDir not found.".to_string());}
		}
	// DependsOn
	let mut depends_on : Vec<String> = vec![];
	match attrs.remove("DependsOn") {
			Some(v) =>
			{
				for item in v.split_str(";").collect::<Vec<&str>>().iter() {
						depends_on.push(item.to_string())
				}
			}
			_ =>
			{
			}
		};

		Ok(XgTask {
	id: attrs.remove("Name"),
	title: attrs.remove("Caption"),
	tool: tool,
	working_dir: working_dir,
	depends_on: depends_on,
	})
}
fn xg_parse_tool (attributes: &Vec<xml::attribute::OwnedAttribute>)->Result<XgTool, String> {
	let mut attrs = map_attributes(attributes);
	// Name
	let id: String;
	match attrs.remove("Name") {
			Some(v) => {id = v;}
			_ => {return Err("Invalid task data: attribute @Name not found.".to_string());}
		}
	// Path
	let path: String;
	match attrs.remove("Path") {
			Some(v) => {path = v;}
			_ => {return Err("Invalid task data: attribute @Name not found.".to_string());}
		}

	Ok(XgTool {
	id: id,
	path: path,
	params: match attrs.remove("Params") {
			Some(v) => {v}
			_ => {"".to_string()}
		},
	})
}
<|endoftext|>


<commit_before>extern crate iron;
#[macro_use]
extern crate mime;
#[macro_use]
extern crate router;

use iron::{Iron, Request, Response, status, IronResult};
use router::Router;
use std::io::prelude::*;
use std::fs::File;

fn main() {
    let router = router!(root: get "/" => handle_root,
                         contact: get "/contact" => handle_contact,
                         quiz: get "/quiz" => handle_quiz);
    Iron::new(router).http("localhost:8080").unwrap();
}

fn handle_root(_: &mut Request) -> IronResult<Response> {
    let content_type = mime!(Text / Html);
    let site = get_site("res/index.html");
    Ok(Response::with((content_type, status::Ok, site)))
}

fn handle_contact(req: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Ferner Fanclub")))
}

fn handle_quiz(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Quizboiss")))
}

fn get_site(path: &str) -> String {
    match File::open(path) {
        Err(_) => return get_site_not_found(path),
        Ok(mut val) => {
            let mut site = String::new();
            match val.read_to_string(&mut site) {
                Err(err) => return get_site_err(err),
                Ok(_) => return site,
            }
        }
    }
}

fn get_site_not_found(path: &str) -> String {
    let msg = format!("404, did not find site at {}", path);
    println!("{}", msg);
    msg
}

fn get_site_err<T: std::fmt::Display>(err: T) -> String {
    let msg = format!("Server error happened\n{}", err);
    println!("{}", msg);
    msg
}
<commit_msg>Test 2<commit_after>extern crate iron;
#[macro_use]
extern crate mime;
#[macro_use]
extern crate router;

use iron::{Iron, Request, Response, status, IronResult};
use router::Router;
use std::io::prelude::*;
use std::fs::File;

fn main() {
    let router = router!(root: get "/" => handle_root,
                         contact: get "/contact" => handle_contact,
                         quiz: get "/quiz" => handle_quiz);
    Iron::new(router).http("localhost:8080").unwrap();
}

fn handle_root(_: &mut Request) -> IronResult<Response> {
    let content_type = mime!(Text / Html);
    let site = get_site("res/index.html");
    Ok(Response::with((content_type, status::Ok, site)))
}

fn handle_contact(req: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Ferner Fanclub")))
}

fn handle_quiz(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Quizbois")))
}

fn get_site(path: &str) -> String {
    match File::open(path) {
        Err(_) => return get_site_not_found(path),
        Ok(mut val) => {
            let mut site = String::new();
            match val.read_to_string(&mut site) {
                Err(err) => return get_site_err(err),
                Ok(_) => return site,
            }
        }
    }
}

fn get_site_not_found(path: &str) -> String {
    let msg = format!("404, did not find site at {}", path);
    println!("{}", msg);
    msg
}

fn get_site_err<T: std::fmt::Display>(err: T) -> String {
    let msg = format!("Server error happened\n{}", err);
    println!("{}", msg);
    msg
}
<|endoftext|>