<commit_before>use super::linux::{dead_processes, MaskSignals, SIGCHLD};
use libc::consts::os::posix88::{SIGTERM, SIGINT, SIGQUIT};
use libc::funcs::posix88::signal::kill;

use libc::{c_int, pid_t};
use collections::treemap::TreeMap;

pub enum Event {
    Signal(c_int),
    Exit(String, pid_t, i32),
}

pub struct Monitor {
    processes: TreeMap<pid_t, String>,
    signalmask: MaskSignals,
    failed: bool,
    exit_code: Option<int>,
    singleton: bool,
}

impl Monitor {
    pub fn new(singleton: bool) -> Monitor {
        Monitor {
            processes: TreeMap::new(),
            signalmask: MaskSignals::new(),
            failed: false,
            singleton: singleton,
            exit_code: None,
        }
    }
    pub fn wait_all(&mut self) {
        while self.processes.len() > 0 {
            match self.next_event() {
                Exit(cname, pid, status) => {
                    if !self.singleton {
                        error!("Process {}:{} dead {}",
                            cname, pid, human_status(status));
                    }
                }
                Signal(sig)
                if sig == SIGTERM || sig == SIGINT || sig == SIGQUIT => {
                    debug!("Got {}. Propagating.", sig);
                    self.send_all(sig);
                }
                Signal(sig) => {
                    debug!("Got {}. Ignoring.", sig);
                }
            }
        }
    }
    pub fn send_all(&mut self, sig: i32) {
        if self.exit_code.is_none() && self.failed {
            self.exit_code = Some(128 + sig as int);
        }
        for (pid, name) in self.processes.iter() {
            unsafe {
                debug!("Sending {} to {}:{}", sig, name, pid);
                kill(*pid, sig);
            }
        }
    }
    pub fn fail(&mut self) {
        self.failed = true;
    }
    pub fn set_exit_status(&mut self, val: int) {
        self.exit_code = Some(val);
    }
    pub fn add(&mut self, name: String, pid: pid_t) {
        assert!(self.processes.insert(pid, name));
    }
    pub fn get_status(&self) -> int {
        return self.exit_code.unwrap_or(0);
    }
    pub fn ok(&self) -> bool {
        return !self.failed && self.processes.len() > 0;
    }
    pub fn next_event(&mut self) -> Event {
        loop {
            for (pid, status) in dead_processes() {
                let (pid, name) = match self.processes.find(&pid) {
                    Some(ref name) => (pid, (*name).clone()),
                    None => {
                        debug!("Unknown process {} exited with {}",
                            pid, status);
                        continue;
                    }
                };
                if self.processes.remove(&pid) && self.singleton {
                    // Translate OS exit code to bash-style exit code
                    if status & 0xff == 0 {
                        // Exit with status
                        self.exit_code = Some(((status >> 8) & 0xff) as int);
                    } else {
                        // Dead on signal
                        self.exit_code = Some((status & 0x7f) as int);
                    }
                }
                return Exit(name, pid, status);
            }
            let sig = self.signalmask.wait();
            if sig == SIGCHLD {
                continue;
            }
            return Signal(sig);
        }
    }
}

pub fn human_status(value: i32) -> String {
    // Note usually pid1 does a status translation too, so 128 + xxx are
    // signals too
    let exit = (value >> 8) & 0xff;
    if value & 0xff == 0 || exit & 0x80 == 0x80 {
        return format!("with exit status {}", (value >> 8) & 0xff);
    } else {
        return format!("on signal {}", value & 0x7f);
    }
}

<commit_msg>Add big nice label on process shutdown<commit_after>use super::linux::{dead_processes, MaskSignals, SIGCHLD};
use libc::consts::os::posix88::{SIGTERM, SIGINT, SIGQUIT};
use libc::funcs::posix88::signal::kill;

use libc::{c_int, pid_t};
use collections::treemap::TreeMap;

pub enum Event {
    Signal(c_int),
    Exit(String, pid_t, i32),
}

pub struct Monitor {
    processes: TreeMap<pid_t, String>,
    signalmask: MaskSignals,
    failed: bool,
    exit_code: Option<int>,
    singleton: bool,
}

impl Monitor {
    pub fn new(singleton: bool) -> Monitor {
        Monitor {
            processes: TreeMap::new(),
            signalmask: MaskSignals::new(),
            failed: false,
            singleton: singleton,
            exit_code: None,
        }
    }
    pub fn wait_all(&mut self) {
        while self.processes.len() > 0 {
            match self.next_event() {
                Exit(cname, pid, status) => {
                    if !self.singleton {
                        error!("Process {}:{} dead {}",
                            cname, pid, human_status(status));
                    }
                }
                Signal(sig)
                if sig == SIGTERM || sig == SIGINT || sig == SIGQUIT => {
                    debug!("Got {}. Propagating.", sig);
                    self.send_all(sig);
                }
                Signal(sig) => {
                    debug!("Got {}. Ignoring.", sig);
                }
            }
        }
    }
    pub fn send_all(&mut self, sig: i32) {
        if self.exit_code.is_none() && self.failed {
            self.exit_code = Some(128 + sig as int);
        }
        for (pid, name) in self.processes.iter() {
            unsafe {
                debug!("Sending {} to {}:{}", sig, name, pid);
                kill(*pid, sig);
            }
        }
    }
    pub fn fail(&mut self) {
        self.failed = true;
        if !self.singleton {
            println!("----------------- SHUTTING DOWN ---------------------");
        }
    }
    pub fn set_exit_status(&mut self, val: int) {
        self.exit_code = Some(val);
    }
    pub fn add(&mut self, name: String, pid: pid_t) {
        assert!(self.processes.insert(pid, name));
    }
    pub fn get_status(&self) -> int {
        return self.exit_code.unwrap_or(0);
    }
    pub fn ok(&self) -> bool {
        return !self.failed && self.processes.len() > 0;
    }
    pub fn next_event(&mut self) -> Event {
        loop {
            for (pid, status) in dead_processes() {
                let (pid, name) = match self.processes.find(&pid) {
                    Some(ref name) => (pid, (*name).clone()),
                    None => {
                        debug!("Unknown process {} exited with {}",
                            pid, status);
                        continue;
                    }
                };
                if self.processes.remove(&pid) && self.singleton {
                    // Translate OS exit code to bash-style exit code
                    if status & 0xff == 0 {
                        // Exit with status
                        self.exit_code = Some(((status >> 8) & 0xff) as int);
                    } else {
                        // Dead on signal
                        self.exit_code = Some((status & 0x7f) as int);
                    }
                }
                return Exit(name, pid, status);
            }
            let sig = self.signalmask.wait();
            if sig == SIGCHLD {
                continue;
            }
            return Signal(sig);
        }
    }
}

pub fn human_status(value: i32) -> String {
    // Note usually pid1 does a status translation too, so 128 + xxx are
    // signals too
    let exit = (value >> 8) & 0xff;
    if value & 0xff == 0 || exit & 0x80 == 0x80 {
        return format!("with exit status {}", (value >> 8) & 0xff);
    } else {
        return format!("on signal {}", value & 0x7f);
    }
}

<|endoftext|>


<commit_before>use std::convert::From;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::Ordering;
use std::sync::mpsc::{Sender, channel};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;
use std::net::SocketAddr;

use VERSION;

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use mio::{EventLoop as MioEventLoop, EventSet, Handler as MioHandler, PollOpt, Token};
use mio::tcp::{Shutdown, TcpListener, TcpStream};
use mio::util::Slab;
use slab::Index;

pub mod client;
pub mod server;
#[cfg(Test)]
pub mod test;

/// The default port for a server to listen on.
pub const STANDARD_PORT: u16 = 25566;
/// Standard number to ensure network connections are syncronized and the same protocol is being used.
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.
const MAX_CONNECTIONS: usize = 1024;

pub enum HandlerMessage {
    Send(NetworkPacket, Token),
    AddStream(TcpStream, Sender<Token>),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        version: String,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
    /// Used to unit test networking. When recived, increments a value. TODO: Locate that value.
    #[cfg(test)]
    Test,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    VersionMismatch(String, String),
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => "VersionMismatch: The versions of the client and server attempting to connect mismatch.",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
        }
    }
}

pub type EventLoop = MioEventLoop<Handler>;
pub struct Handler {
    connections: Slab<Connection>,
    listener: Option<TcpListener>,
}

impl Handler {
    /// Creates a new instance of a Handler. Does not listen for connections.
    pub fn new() -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: None,
        }
    }

    /// Creates a new instance of a Handler. Does listen for connections.
    pub fn new_listener(listener: TcpListener) -> Self {
        Ok(Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: Some(listener),
        })
    }
}

#[derive(Debug)]
struct Connection {
    message_queue: Vec<NetworkPacket>,
    stream: TcpStream,
}

impl Connection {
    fn new(stream: TcpStream) -> Connection {
        Connection {
            stream: stream,
            message_queue: Vec::new(),
        }
    }
}

impl MioHandler for Handler {
    type Timeout = ();
    type Message = HandlerMessage;
    fn ready(&mut self, event_loop: &mut MioEventLoop<Handler>, token: Token, events: EventSet) {
        if events.is_readable() {
            // Read the 6 byte header of each packet, throw it into get_packet_length, then read that number of bytes.
            // Then throw those bytes into deserialize_packet. Afterwards, throw it to handle_packet.

            let mut header = [0; 6];
            self.connections[token]
                .stream
                .read(&mut header)
                .expect(&format!("An error occured reading from socket {:?}", token));    // TODO: Figure out possible errors and take care of them.
            let length = get_packet_length(header).unwrap_or(0);
            if length == 0 {
                event_loop.deregister(&self.connections[token].stream);
                self.connections[token].stream.shutdown(Shutdown::Both);
                self.connections.remove(token);
                // I directly kill the connection, becasue if the magic number doesn't match,
                // the peer probably doesn't share the same protocol. It wouldn't understand a normal error packet.
                return;
            }
            let mut packet = Vec::new();
            (&mut self.connections[token].stream).take(length as u64).read_to_end(&mut packet).unwrap();
            // I do this because Read.take takes a self, instead of a reasonable alternitive.
            // However &mut Read is it's self a Reader. So I use that instead.
            let dese = deserialize_packet(&packet).unwrap();
            handle_packet(dese, token, event_loop);
        }

        if events.is_writable() {
            // Get all the messages that should be send to that token, seralize all of them, then send all of them.
            // Afterwards, flush the buffer.
            let to_send = self.connections[token].message_queue.clone();
            self.connections[token].message_queue = Vec::new();
            if !to_send.is_empty() {
                for send in to_send {
                    let bytes = seralize_packet(&send);
                    self.connections[token]
                        .stream
                        .write(&bytes)
                        .expect(&format!("Error writing {:?} to connection {:?}/{:?}",
                                         send,
                                         token,
                                         self.connections[token]));
                }
                self.connections[token]
                    .stream
                    .flush()
                    .expect(&format!("Error flushing connection {:?}/{:?}",
                                     token,
                                     self.connections[token]));;
            }
        }

        if self.listener.is_some() {
            match self.listener.as_ref().unwrap().accept() {
                Ok(Some((socket, address))) => {
                    let token = self.connections.insert(Connection::new(socket)).unwrap();
                    send(event_loop,
                         NetworkPacket::Init { version: VERSION.to_owned() },
                         token);
                    info!("Accepted connection {}.", address);
                }
                Ok(None) => debug!("Recived Ok(None) in listener.accept()."),
                Err(error) => panic!("listener.accept() errored with {:?}!", error),
                // TODO: See if any of these errors can be handled better.
            }
        }
    }

    fn notify(&mut self, event_loop: &mut MioEventLoop<Handler>, msg: HandlerMessage) {
        match msg {
            HandlerMessage::AddStream(stream, tx) => {
                let token = self.connections.insert(Connection::new(stream)).unwrap();
                event_loop.register(&self.connections[token].stream,
                                    token,
                                    EventSet::all(),
                                    PollOpt::level())
                          .unwrap();
                tx.send(token).unwrap();
            }
            HandlerMessage::Send(packet, token) => {
                self.connections[token].message_queue.push(packet);
            }
        }
    }
}

fn add_socket(event_loop: &EventLoop, socket: TcpStream) -> Token {
    let (tx, rx) = channel();   // How expensive is this? Should I be creating a whole new channel for just 1 message?
    event_loop.channel().send(HandlerMessage::AddStream(socket, tx)).unwrap();
    rx.recv().unwrap() // I should feel bad.
}

/// Send a NetworkPacket over the network.
///
/// This is a static function instead of an impl function because you can't impl on external structs. In this case, mio::EventLoop.
pub fn send(event_loop: &EventLoop, to_send: NetworkPacket, token: Token) {
    event_loop.channel().send(HandlerMessage::Send(to_send, token)).unwrap();
}

fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}

#[derive(Debug)]
enum PacketDeseError {
    MagicNumberMismatch,
    InvalidEncoding(DeserializeError),
}

impl From<DeserializeError> for PacketDeseError {
    fn from(err: DeserializeError) -> PacketDeseError {
        PacketDeseError::InvalidEncoding(err)
    }
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, PacketDeseError> {
    Ok(try!(deserialize::<NetworkPacket>(to_de)))
}

fn handle_packet(to_handle: NetworkPacket, sender: Token, event_loop: &EventLoop) {
    match to_handle {
        NetworkPacket::Init{version} => {
            if version != VERSION {
                send(event_loop,
                     NetworkPacket::Error(NetworkError::VersionMismatch(version.to_owned(), VERSION.to_owned())),
                     sender)
            }
        }

        #[cfg(Test)]
        NetworkPacket::Test => test::TEST_INT.fetch_add(1, Ordering::Relaxed),

        NetworkPacket::Error(error) => if ::check_should_crash() { panic!(error) } else { unimplemented!() },
    }
}
<commit_msg>Fix compile error after the last commit<commit_after>use std::convert::From;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::Ordering;
use std::sync::mpsc::{Sender, channel};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;
use std::net::SocketAddr;

use VERSION;

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use mio::{EventLoop as MioEventLoop, EventSet, Handler as MioHandler, PollOpt, Token};
use mio::tcp::{Shutdown, TcpListener, TcpStream};
use mio::util::Slab;
use slab::Index;

pub mod client;
#[cfg(Test)]
pub mod test;

/// The default port for a server to listen on.
pub const STANDARD_PORT: u16 = 25566;
/// Standard number to ensure network connections are syncronized and the same protocol is being used.
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.
const MAX_CONNECTIONS: usize = 1024;

pub enum HandlerMessage {
    Send(NetworkPacket, Token),
    AddStream(TcpStream, Sender<Token>),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        version: String,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
    /// Used to unit test networking. When recived, increments a value. TODO: Locate that value.
    #[cfg(test)]
    Test,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    VersionMismatch(String, String),
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => "VersionMismatch: The versions of the client and server attempting to connect mismatch.",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
        }
    }
}

pub type EventLoop = MioEventLoop<Handler>;
pub struct Handler {
    connections: Slab<Connection>,
    listener: Option<TcpListener>,
}

impl Handler {
    /// Creates a new instance of a Handler. Does not listen for connections.
    pub fn new() -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: None,
        }
    }

    /// Creates a new instance of a Handler. Does listen for connections.
    pub fn new_listener(listener: TcpListener) -> Self {
        Ok(Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: Some(listener),
        })
    }
}

#[derive(Debug)]
struct Connection {
    message_queue: Vec<NetworkPacket>,
    stream: TcpStream,
}

impl Connection {
    fn new(stream: TcpStream) -> Connection {
        Connection {
            stream: stream,
            message_queue: Vec::new(),
        }
    }
}

impl MioHandler for Handler {
    type Timeout = ();
    type Message = HandlerMessage;
    fn ready(&mut self, event_loop: &mut MioEventLoop<Handler>, token: Token, events: EventSet) {
        if events.is_readable() {
            // Read the 6 byte header of each packet, throw it into get_packet_length, then read that number of bytes.
            // Then throw those bytes into deserialize_packet. Afterwards, throw it to handle_packet.

            let mut header = [0; 6];
            self.connections[token]
                .stream
                .read(&mut header)
                .expect(&format!("An error occured reading from socket {:?}", token));    // TODO: Figure out possible errors and take care of them.
            let length = get_packet_length(header).unwrap_or(0);
            if length == 0 {
                event_loop.deregister(&self.connections[token].stream);
                self.connections[token].stream.shutdown(Shutdown::Both);
                self.connections.remove(token);
                // I directly kill the connection, becasue if the magic number doesn't match,
                // the peer probably doesn't share the same protocol. It wouldn't understand a normal error packet.
                return;
            }
            let mut packet = Vec::new();
            (&mut self.connections[token].stream).take(length as u64).read_to_end(&mut packet).unwrap();
            // I do this because Read.take takes a self, instead of a reasonable alternitive.
            // However &mut Read is it's self a Reader. So I use that instead.
            let dese = deserialize_packet(&packet).unwrap();
            handle_packet(dese, token, event_loop);
        }

        if events.is_writable() {
            // Get all the messages that should be send to that token, seralize all of them, then send all of them.
            // Afterwards, flush the buffer.
            let to_send = self.connections[token].message_queue.clone();
            self.connections[token].message_queue = Vec::new();
            if !to_send.is_empty() {
                for send in to_send {
                    let bytes = seralize_packet(&send);
                    self.connections[token]
                        .stream
                        .write(&bytes)
                        .expect(&format!("Error writing {:?} to connection {:?}/{:?}",
                                         send,
                                         token,
                                         self.connections[token]));
                }
                self.connections[token]
                    .stream
                    .flush()
                    .expect(&format!("Error flushing connection {:?}/{:?}",
                                     token,
                                     self.connections[token]));;
            }
        }

        if self.listener.is_some() {
            match self.listener.as_ref().unwrap().accept() {
                Ok(Some((socket, address))) => {
                    let token = self.connections.insert(Connection::new(socket)).unwrap();
                    send(event_loop,
                         NetworkPacket::Init { version: VERSION.to_owned() },
                         token);
                    info!("Accepted connection {}.", address);
                }
                Ok(None) => debug!("Recived Ok(None) in listener.accept()."),
                Err(error) => panic!("listener.accept() errored with {:?}!", error),
                // TODO: See if any of these errors can be handled better.
            }
        }
    }

    fn notify(&mut self, event_loop: &mut MioEventLoop<Handler>, msg: HandlerMessage) {
        match msg {
            HandlerMessage::AddStream(stream, tx) => {
                let token = self.connections.insert(Connection::new(stream)).unwrap();
                event_loop.register(&self.connections[token].stream,
                                    token,
                                    EventSet::all(),
                                    PollOpt::level())
                          .unwrap();
                tx.send(token).unwrap();
            }
            HandlerMessage::Send(packet, token) => {
                self.connections[token].message_queue.push(packet);
            }
        }
    }
}

fn add_socket(event_loop: &EventLoop, socket: TcpStream) -> Token {
    let (tx, rx) = channel();   // How expensive is this? Should I be creating a whole new channel for just 1 message?
    event_loop.channel().send(HandlerMessage::AddStream(socket, tx)).unwrap();
    rx.recv().unwrap() // I should feel bad.
}

/// Send a NetworkPacket over the network.
///
/// This is a static function instead of an impl function because you can't impl on external structs. In this case, mio::EventLoop.
pub fn send(event_loop: &EventLoop, to_send: NetworkPacket, token: Token) {
    event_loop.channel().send(HandlerMessage::Send(to_send, token)).unwrap();
}

fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}

#[derive(Debug)]
enum PacketDeseError {
    MagicNumberMismatch,
    InvalidEncoding(DeserializeError),
}

impl From<DeserializeError> for PacketDeseError {
    fn from(err: DeserializeError) -> PacketDeseError {
        PacketDeseError::InvalidEncoding(err)
    }
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, PacketDeseError> {
    Ok(try!(deserialize::<NetworkPacket>(to_de)))
}

fn handle_packet(to_handle: NetworkPacket, sender: Token, event_loop: &EventLoop) {
    match to_handle {
        NetworkPacket::Init{version} => {
            if version != VERSION {
                send(event_loop,
                     NetworkPacket::Error(NetworkError::VersionMismatch(version.to_owned(), VERSION.to_owned())),
                     sender)
            }
        }

        #[cfg(Test)]
        NetworkPacket::Test => test::TEST_INT.fetch_add(1, Ordering::Relaxed),

        NetworkPacket::Error(error) => if ::check_should_crash() { panic!(error) } else { unimplemented!() },
    }
}
<|endoftext|>


<commit_before>//! Read points from las files.

use std::fs::File;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::path::Path;

use byteorder::LittleEndian;
use byteorder::ReadBytesExt;

use num::FromPrimitive;

use Result;
use header::Header;
use point::Classification;
use point::Point;
use point::ScanDirection;

pub struct Reader<R: Read + Seek> {
    header: Header,
    reader: R,
}

impl<R: Read + Seek> Reader<R> {
    /// Creates a reader for a `Read` object.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let stream = std::fs::File::open("data/1.2_0.las").unwrap();
    /// let reader = Reader::new(stream);
    /// ```
    pub fn new(mut reader: R) -> Result<Reader<R>> {
        Ok(Reader {
            header: try!(Header::new(&mut reader)),
            reader: reader,
        })
    }

    /// Returns the `Header`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let reader = Reader::open("data/1.2_0.las").unwrap();
    /// let header = reader.header();
    /// assert_eq!(*b"LASF", header.file_signature);
    /// ```
    pub fn header(&self) -> &Header { &self.header }

    /// Returns a vector of all the points in the lasfile.
    ///
    /// Only use this method if you really do want to load all the points into memory at once.
    /// Otherwise, use the provided iterator methods to scan through the points in a more efficient
    /// manner.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let mut reader = Reader::open("data/1.2_0.las").unwrap();
    /// let points = reader.points().unwrap();
    /// assert_eq!(1, points.len());
    /// ```
    pub fn points(&mut self) -> Result<Vec<Point>> {
        Ok(try!(self.points_iter()).collect())
    }

    /// Creates an interator over this reader's points.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// # use las::point::Point;
    /// let mut reader = Reader::open("data/1.2_0.las").unwrap();
    /// let points: Vec<Point> = reader.points_iter().unwrap().collect();
    /// assert_eq!(1, points.len());
    /// ```
    pub fn points_iter(&mut self) -> Result<PointsIterator<R>> {
        try!(self.reader.seek(SeekFrom::Start(self.header.offset_to_point_data as u64)));
        Ok(PointsIterator {
            reader: self,
        })
    }

    /// Reads and returns the next point from the reader.
    fn next_point(&mut self) -> Result<Point> {
        let mut point: Point = Default::default();
        point.x = try!(self.reader.read_u32::<LittleEndian>()) as f64 * self.header.scale.x +
            self.header.offset.x;
        point.y = try!(self.reader.read_u32::<LittleEndian>()) as f64 * self.header.scale.y +
            self.header.offset.y;
        point.z = try!(self.reader.read_u32::<LittleEndian>()) as f64 * self.header.scale.z +
            self.header.offset.z;
        point.intensity = try!(self.reader.read_u16::<LittleEndian>());
        let byte = try!(self.reader.read_u8());
        point.return_number = byte & 0b00000111;
        point.number_of_returns = byte >> 3 & 0b00000111;
        point.scan_direction = match ScanDirection::from_u8(byte >> 6 & 0b00000001) {
            Some(scan_direction) => scan_direction,
            None => unreachable!(),
        };
        point.edge_of_flight_line = (byte >> 7 & 0b00000001) == 1;
        point.classification = match Classification::from_u8(try!(self.reader.read_u8())) {
            Some(classification) => classification,
            None => Default::default(),
        };
        point.scan_angle_rank = try!(self.reader.read_u8());
        point.user_data = try!(self.reader.read_u8());
        point.point_source_id = try!(self.reader.read_u16::<LittleEndian>());
        Ok(point)
    }
}

impl Reader<File> {
    /// Opens a reader for a given file path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let reader = Reader::open("data/1.2_0.las");
    /// ```
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Reader<File>> {
        // TODO wrap in BufRead
        let reader = try!(File::open(path));
        Ok(try!(Reader::new(reader)))
    }
}

/// Iterator over the points of a reader.
///
/// The iterator starts at the first point and reads through to the end.
pub struct PointsIterator<'a, R: 'a + Read + Seek> {
    reader: &'a mut Reader<R>,
}

impl<'a, R: Read + Seek> Iterator for PointsIterator<'a, R> {
    type Item = Point;

    fn next(&mut self) -> Option<Point> {
        self.reader.next_point().ok()
    }
}

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

    use point::Classification;
    use point::Point;
    use point::ScanDirection;

    #[test]
    fn header() {
        let reader = Reader::open("data/1.2_0.las").unwrap();
        let header = reader.header();
        assert_eq!(*b"LASF", header.file_signature);
        assert_eq!(0, header.file_source_id);
        assert_eq!(0, header.global_encoding);
        assert_eq!("b8f18883-1baa-0841-bca3-6bc68e7b062e", header.project_id.as_string());
        assert_eq!(1, header.version_major);
        assert_eq!(2, header.version_minor);
        assert_eq!("libLAS", header.system_identifier);
        assert_eq!("libLAS 1.2", header.generating_software);
        assert_eq!(78, header.file_creation_day_of_year);
        assert_eq!(2008, header.file_creation_year);
        assert_eq!(227, header.header_size);
        assert_eq!(438, header.offset_to_point_data);
        assert_eq!(2, header.number_of_variable_length_records);
        assert_eq!(0, header.point_data_format_id);
        assert_eq!(20, header.point_data_record_length);
        assert_eq!(1, header.number_of_point_records);
        assert_eq!([0, 1, 0, 0, 0], header.number_of_points_by_return);
        assert_eq!(0.01, header.scale.x);
        assert_eq!(0.01, header.scale.y);
        assert_eq!(0.01, header.scale.z);
        assert_eq!(0.0, header.offset.x);
        assert_eq!(0.0, header.offset.y);
        assert_eq!(0.0, header.offset.z);
        assert_eq!(470692.447538, header.min.x);
        assert_eq!(4602888.904642, header.min.y);
        assert_eq!(16.0, header.min.z);
        assert_eq!(470692.447538, header.max.x);
        assert_eq!(4602888.904642, header.max.y);
        assert_eq!(16.0, header.max.z);
    }

    #[test]
    fn points() {
        let mut reader = Reader::open("data/1.2_0.las").unwrap();
        let points: Vec<Point> = reader.points_iter().unwrap().collect();
        assert_eq!(1, points.len());
        let point = &points[0];
        assert_eq!(470692.44, point.x);
        assert_eq!(4602888.90, point.y);
        assert_eq!(16.0, point.z);
        assert_eq!(0, point.intensity);
        assert_eq!(2, point.return_number);
        assert_eq!(0, point.number_of_returns);
        assert_eq!(ScanDirection::Backward, point.scan_direction);
        assert!(!point.edge_of_flight_line);
        assert_eq!(Classification::Ground, point.classification);
        assert_eq!(-13, point.scan_angle_rank);
        assert_eq!(0, point.user_data);
        assert_eq!(0, point.point_source_id);
    }
}
<commit_msg>Refactor test to make it easier to test various formats<commit_after>//! Read points from las files.

use std::fs::File;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::path::Path;

use byteorder::LittleEndian;
use byteorder::ReadBytesExt;

use num::FromPrimitive;

use Result;
use header::Header;
use point::Classification;
use point::Point;
use point::ScanDirection;

pub struct Reader<R: Read + Seek> {
    header: Header,
    reader: R,
}

impl<R: Read + Seek> Reader<R> {
    /// Creates a reader for a `Read` object.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let stream = std::fs::File::open("data/1.2_0.las").unwrap();
    /// let reader = Reader::new(stream);
    /// ```
    pub fn new(mut reader: R) -> Result<Reader<R>> {
        Ok(Reader {
            header: try!(Header::new(&mut reader)),
            reader: reader,
        })
    }

    /// Returns the `Header`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let reader = Reader::open("data/1.2_0.las").unwrap();
    /// let header = reader.header();
    /// assert_eq!(*b"LASF", header.file_signature);
    /// ```
    pub fn header(&self) -> &Header { &self.header }

    /// Returns a vector of all the points in the lasfile.
    ///
    /// Only use this method if you really do want to load all the points into memory at once.
    /// Otherwise, use the provided iterator methods to scan through the points in a more efficient
    /// manner.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let mut reader = Reader::open("data/1.2_0.las").unwrap();
    /// let points = reader.points().unwrap();
    /// assert_eq!(1, points.len());
    /// ```
    pub fn points(&mut self) -> Result<Vec<Point>> {
        Ok(try!(self.points_iter()).collect())
    }

    /// Creates an interator over this reader's points.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// # use las::point::Point;
    /// let mut reader = Reader::open("data/1.2_0.las").unwrap();
    /// let points: Vec<Point> = reader.points_iter().unwrap().collect();
    /// assert_eq!(1, points.len());
    /// ```
    pub fn points_iter(&mut self) -> Result<PointsIterator<R>> {
        try!(self.reader.seek(SeekFrom::Start(self.header.offset_to_point_data as u64)));
        Ok(PointsIterator {
            reader: self,
        })
    }

    /// Reads and returns the next point from the reader.
    fn next_point(&mut self) -> Result<Point> {
        let mut point: Point = Default::default();
        point.x = try!(self.reader.read_u32::<LittleEndian>()) as f64 * self.header.scale.x +
            self.header.offset.x;
        point.y = try!(self.reader.read_u32::<LittleEndian>()) as f64 * self.header.scale.y +
            self.header.offset.y;
        point.z = try!(self.reader.read_u32::<LittleEndian>()) as f64 * self.header.scale.z +
            self.header.offset.z;
        point.intensity = try!(self.reader.read_u16::<LittleEndian>());
        let byte = try!(self.reader.read_u8());
        point.return_number = byte & 0b00000111;
        point.number_of_returns = byte >> 3 & 0b00000111;
        point.scan_direction = match ScanDirection::from_u8(byte >> 6 & 0b00000001) {
            Some(scan_direction) => scan_direction,
            None => unreachable!(),
        };
        point.edge_of_flight_line = (byte >> 7 & 0b00000001) == 1;
        point.classification = match Classification::from_u8(try!(self.reader.read_u8())) {
            Some(classification) => classification,
            None => Default::default(),
        };
        point.scan_angle_rank = try!(self.reader.read_u8());
        point.user_data = try!(self.reader.read_u8());
        point.point_source_id = try!(self.reader.read_u16::<LittleEndian>());
        Ok(point)
    }
}

impl Reader<File> {
    /// Opens a reader for a given file path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::reader::Reader;
    /// let reader = Reader::open("data/1.2_0.las");
    /// ```
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Reader<File>> {
        // TODO wrap in BufRead
        let reader = try!(File::open(path));
        Ok(try!(Reader::new(reader)))
    }
}

/// Iterator over the points of a reader.
///
/// The iterator starts at the first point and reads through to the end.
pub struct PointsIterator<'a, R: 'a + Read + Seek> {
    reader: &'a mut Reader<R>,
}

impl<'a, R: Read + Seek> Iterator for PointsIterator<'a, R> {
    type Item = Point;

    fn next(&mut self) -> Option<Point> {
        self.reader.next_point().ok()
    }
}

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

    use point::Classification;
    use point::Point;
    use point::ScanDirection;

    fn check_point(point: &Point, point_format: u8) {
        assert_eq!(470692.44, point.x);
        assert_eq!(4602888.90, point.y);
        assert_eq!(16.0, point.z);
        assert_eq!(0, point.intensity);
        assert_eq!(2, point.return_number);
        assert_eq!(0, point.number_of_returns);
        assert_eq!(ScanDirection::Backward, point.scan_direction);
        assert!(!point.edge_of_flight_line);
        assert_eq!(Classification::Ground, point.classification);
        assert_eq!(-13, point.scan_angle_rank);
        assert_eq!(0, point.user_data);
        assert_eq!(0, point.point_source_id);
    }

    #[test]
    fn header() {
        let reader = Reader::open("data/1.2_0.las").unwrap();
        let header = reader.header();
        assert_eq!(*b"LASF", header.file_signature);
        assert_eq!(0, header.file_source_id);
        assert_eq!(0, header.global_encoding);
        assert_eq!("b8f18883-1baa-0841-bca3-6bc68e7b062e", header.project_id.as_string());
        assert_eq!(1, header.version_major);
        assert_eq!(2, header.version_minor);
        assert_eq!("libLAS", header.system_identifier);
        assert_eq!("libLAS 1.2", header.generating_software);
        assert_eq!(78, header.file_creation_day_of_year);
        assert_eq!(2008, header.file_creation_year);
        assert_eq!(227, header.header_size);
        assert_eq!(438, header.offset_to_point_data);
        assert_eq!(2, header.number_of_variable_length_records);
        assert_eq!(0, header.point_data_format_id);
        assert_eq!(20, header.point_data_record_length);
        assert_eq!(1, header.number_of_point_records);
        assert_eq!([0, 1, 0, 0, 0], header.number_of_points_by_return);
        assert_eq!(0.01, header.scale.x);
        assert_eq!(0.01, header.scale.y);
        assert_eq!(0.01, header.scale.z);
        assert_eq!(0.0, header.offset.x);
        assert_eq!(0.0, header.offset.y);
        assert_eq!(0.0, header.offset.z);
        assert_eq!(470692.447538, header.min.x);
        assert_eq!(4602888.904642, header.min.y);
        assert_eq!(16.0, header.min.z);
        assert_eq!(470692.447538, header.max.x);
        assert_eq!(4602888.904642, header.max.y);
        assert_eq!(16.0, header.max.z);
    }

    #[test]
    fn points() {
        let mut reader = Reader::open("data/1.2_0.las").unwrap();
        let points: Vec<Point> = reader.points_iter().unwrap().collect();
        assert_eq!(1, points.len());
        let point = &points[0];
        check_point(point, 0);
    }
}
<|endoftext|>


<commit_before>use super::innovation::{Innovation, InnovationContainer};
use super::traits::{Distance, Genotype};
use super::alignment::Alignment;
use std::cmp;
use super::crossover::Crossover;
use rand::Rng;
use fixedbitset::FixedBitSet;
use std::collections::BTreeMap;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum NodeType {
    Input,
    Output,
    Hidden,
}

impl Default for NodeType {
    fn default() -> Self {
        NodeType::Hidden
    }
}

#[derive(Debug, Clone)]
pub struct NodeGene {
    pub node_type: NodeType,
}

// To avoid node collisions we use Innovation numbers instead of node
// ids.
#[derive(Debug, Clone)]
pub struct LinkGene {
    // This points to the NodeGene of that innovation
    pub source_node_gene: Innovation,
    // This points to the NodeGene of that innovation
    pub target_node_gene: Innovation,
    pub weight: f64,
    pub active: bool,
}

impl LinkGene {
    pub fn disable(&mut self) {
        assert!(self.active);
        self.active = false;
    }
}

#[derive(Debug, Clone)]
pub struct NetworkGenome {
    pub link_genes: InnovationContainer<LinkGene>,
    pub node_genes: InnovationContainer<NodeGene>,
}

#[derive(Debug, Clone)]
struct AdjMatrix {
    n: usize,
    m: FixedBitSet,
}

impl AdjMatrix {
    fn new(n: usize) -> AdjMatrix {
        AdjMatrix {
            n: n,
            m: FixedBitSet::with_capacity(n * n),
        }
    }

    fn set(&mut self, i: usize, j: usize) {
        self.m.insert(i * self.n + j);
    }

    fn contains(&self, i: usize, j: usize) -> bool {
        self.m.contains(i * self.n + j)
    }

    /// This is O(n**4) in worst case.
    /// XXX: This needs a test for correctness
    fn transitive_closure(mut self) -> AdjMatrix {
        loop {
            let mut counts = 0;
            for i in 0..self.n {
                for j in 0..self.n {
                    if self.contains(i, j) {
                        // look column for j
                        for k in 0..self.n {
                            if self.contains(j, k) {
                                if !self.contains(i, k) {
                                    self.set(i, k);
                                    counts += 1;
                                }
                            }
                        }
                    }
                }
            }
            if counts == 0 {
                break;
            }
        }
        self
    }

    fn unconnected_pairs_no_cycle(&self) -> Vec<(usize, usize)> {
        let mut pairs = Vec::new();
        for i in 0..self.n {
            for j in 0..self.n {
                if i != j {
                    if !(self.contains(i, j) || self.contains(j, i)) {
                        // make sure we don't introduce a cycle
                        pairs.push((i, j));
                    }
                }
            }
        }
        pairs
    }
}

impl NetworkGenome {
    // Uses the crossover method C to recombine left and right.
    pub fn crossover<R: Rng, C: Crossover>(left: &Self, right: &Self, c: &C, rng: &mut R) -> Self {
        let new_link_genes = c.crossover(&left.link_genes, &right.link_genes, rng);
        let mut new_node_genes = c.crossover(&left.node_genes, &right.node_genes, rng);

        // Additionally make sure that all link genes have a correspondant node gene.
        // We do this also for disabled links!
        for link in new_link_genes.map.values() {
            new_node_genes.insert_from_either_or(link.source_node_gene,
                                                 &left.node_genes,
                                                 &right.node_genes);
            new_node_genes.insert_from_either_or(link.target_node_gene,
                                                 &left.node_genes,
                                                 &right.node_genes);
        }

        NetworkGenome {
            link_genes: new_link_genes,
            node_genes: new_node_genes,
        }
    }

    /// Constructs the adjacency matrix from the genome.
    fn adjacency_matrix(&self) -> (AdjMatrix, Vec<Innovation>) {
        // map the node innovation to the index in the adjacency matrix
        let mut map_to_indices: BTreeMap<Innovation, usize> = BTreeMap::new();
        // and the reverse map from index to Innovation
        let mut rev_map: Vec<Innovation> = Vec::new();

        for &node_innov in self.node_genes.map.keys() {
            let next_idx = rev_map.len();
            rev_map.push(node_innov);
            let prev = map_to_indices.insert(node_innov, next_idx);
            assert!(prev.is_none());
        }

        assert!(rev_map.len() == map_to_indices.len());

        let n = map_to_indices.len();
        let mut adj_matrix = AdjMatrix::new(n);
        for link in self.link_genes.map.values() {
            if link.active {
                adj_matrix.set(map_to_indices[&link.source_node_gene],
                               map_to_indices[&link.target_node_gene]);
            }
        }

        (adj_matrix, rev_map)
    }

    /// Returns a random link gene innovation which is active. Or None if no such exists.
    pub fn find_random_active_link_gene<R: Rng>(&self, rng: &mut R) -> Option<Innovation> {
        let mut all_active_link_innovations = Vec::with_capacity(self.link_genes.len());
        for (&innov, link) in self.link_genes.map.iter() {
            if link.active {
                all_active_link_innovations.push(innov);
            }
        }
        rng.choose(&all_active_link_innovations).map(|&i| i)
    }

    /// Returns two node innvovations which are not yet connected and which does not
    /// create a cycle. Return `None` if no such connection exists.
    pub fn find_random_unconnected_pair<R: Rng>(&self,
                                                rng: &mut R)
                                                -> Option<(Innovation, Innovation)> {
        // Construct binary adjacency matrix
        let (adj_matrix, rev_map) = self.adjacency_matrix();

        // Construct an array of all currently unconnected nodes.
        let unconnected = adj_matrix.transitive_closure().unconnected_pairs_no_cycle();

        // Out of all unconnected pairs, choose a random one.
        rng.choose(&unconnected).map(|&(source, target)| {
            // reverse map src and target to the node innovation
            (rev_map[source], rev_map[target])
        })
    }
}

impl Genotype for NetworkGenome {}

struct LinkGeneWeightDistance;

impl Distance<LinkGene> for LinkGeneWeightDistance {
    fn distance(&self, a: &LinkGene, b: &LinkGene) -> f64 {
        a.weight - b.weight
    }
}

pub struct LinkGeneListDistance {
    pub excess: f64,
    pub disjoint: f64,
    pub weight: f64,
}

impl Distance<InnovationContainer<LinkGene>> for LinkGeneListDistance {
    fn distance(&self,
                genes_left: &InnovationContainer<LinkGene>,
                genes_right: &InnovationContainer<LinkGene>)
                -> f64 {
        let max_len = cmp::max(genes_left.len(), genes_right.len());
        if max_len == 0 {
            return 0.0;
        }

        let mut matching = 0;
        let mut disjoint = 0;
        let mut excess = 0;
        let mut weight_dist = 0.0;

        genes_left.align(genes_right,
                         &mut |_, alignment| {
                             match alignment {
                                 Alignment::Match(gene_left, gene_right) => {
                                     matching += 1;
                                     weight_dist += LinkGeneWeightDistance.distance(gene_left,
                                                                                gene_right)
                                                                          .abs();
                                 }
                                 Alignment::DisjointLeft(_) | Alignment::DisjointRight(_) => {
                                     disjoint += 1;
                                 }
                                 Alignment::ExcessLeft(_) | Alignment::ExcessRight(_) => {
                                     excess += 1;
                                 }
                             }
                         });

        assert!(2 * matching + disjoint + excess == genes_left.len() + genes_right.len());

        self.excess * (excess as f64) / (max_len as f64) +
        self.disjoint * (disjoint as f64) / (max_len as f64) +
        self.weight *
        if matching > 0 {
            weight_dist / (matching as f64)
        } else {
            0.0
        }
    }
}

pub struct NetworkGenomeDistance {
    pub l: LinkGeneListDistance,
}

impl Distance<NetworkGenome> for NetworkGenomeDistance {
    fn distance(&self, genome_left: &NetworkGenome, genome_right: &NetworkGenome) -> f64 {
        self.l.distance(&genome_left.link_genes, &genome_right.link_genes)
    }
}

pub struct Environment {
    node_innovation_counter: Innovation,
    link_innovation_counter: Innovation,
    // (src_node, target_node) -> link_innovation
    link_innovation_cache: BTreeMap<(Innovation, Innovation), Innovation>,
}

impl Environment {
    pub fn new() -> Environment {
        Environment {
            node_innovation_counter: Innovation::new(0),
            link_innovation_counter: Innovation::new(0),
            link_innovation_cache: BTreeMap::new(),
        }
    }

    // XXX
    fn random_link_weight<R: Rng>(&mut self, rng: &mut R) -> f64 {
        // XXX Choose a weight between -1 and 1?
        rng.gen()
    }

    fn add_link<R: Rng>(&mut self,
                        genome: &mut NetworkGenome,
                        source_node: Innovation,
                        target_node: Innovation,
                        rng: &mut R) {
        let link_gene = LinkGene {
            source_node_gene: source_node,
            target_node_gene: target_node,
            weight: self.random_link_weight(rng),
            active: true,
        };
        self.add_link_gene(genome, link_gene);
    }

    fn add_link_gene(&mut self, genome: &mut NetworkGenome, link_gene: LinkGene) {
        let link_innovation = self.get_link_innovation(link_gene.source_node_gene,
                                                       link_gene.target_node_gene);
        genome.link_genes.insert_or_replace(link_innovation, link_gene);
    }

    fn get_link_innovation(&mut self,
                           source_node_gene: Innovation,
                           target_node_gene: Innovation)
                           -> Innovation {
        let key = (source_node_gene, target_node_gene);
        if let Some(&cached_innovation) = self.link_innovation_cache.get(&key) {
            return cached_innovation;
        }
        let new_innovation = self.link_innovation_counter.next().unwrap();
        self.link_innovation_cache.insert(key, new_innovation);
        new_innovation
    }

    pub fn mutate_add_connection<R: Rng>(&mut self,
                                         genome: &NetworkGenome,
                                         rng: &mut R)
                                         -> Option<NetworkGenome> {
        genome.find_random_unconnected_pair(rng).map(|(src, target)| {
            let mut offspring = genome.clone();
            // Add new link to the offspring genome
            self.add_link(&mut offspring, src, target, rng);
            offspring
        })
    }

    /// choose a random link. split it in half.
    pub fn mutate_add_node<R: Rng>(&mut self,
                                   genome: &NetworkGenome,
                                   rng: &mut R)
                                   -> Option<NetworkGenome> {
        if let Some(link_innov) = genome.find_random_active_link_gene(rng) {
            // split link in half.
            let mut offspring = genome.clone();
            let new_node_innovation = self.new_node_innovation();
            // add new node
            offspring.node_genes.insert(new_node_innovation,
                                        NodeGene { node_type: NodeType::Hidden });
            // disable `link_innov` in offspring
            // we keep this gene (but disable it), because this allows us to have a structurally
            // compatible genome to the old one, as disabled genes are taken into account for
            // the genomic distance measure.
            offspring.link_genes.get_mut(&link_innov).unwrap().disable();
            // add two new link innovations with the new node in the middle.
            // XXX: Choose random weights? Or split weight? We use random weights for now.
            let (orig_src_node, orig_target_node) = {
                let orig_link = offspring.link_genes.get(&link_innov).unwrap();
                (orig_link.source_node_gene, orig_link.target_node_gene)
            };
            self.add_link(&mut offspring, orig_src_node, new_node_innovation, rng);
            self.add_link(&mut offspring, new_node_innovation, orig_target_node, rng);
            Some(offspring)
        } else {
            None
        }
    }

    fn new_node_innovation(&mut self) -> Innovation {
        self.node_innovation_counter.next().unwrap()
    }

    // Generates a NetworkGenome with `n_inputs` input nodes and `n_outputs` output nodes.
    // The genome will not have any link nodes.
    pub fn generate_genome(&mut self, n_inputs: usize, n_outputs: usize) -> NetworkGenome {
        assert!(n_inputs > 0 && n_outputs > 0);
        let mut nodes = InnovationContainer::new();
        for _ in 0..n_inputs {
            nodes.insert(self.node_innovation_counter.next().unwrap(),
                         NodeGene { node_type: NodeType::Input });
        }
        assert!(nodes.len() == n_inputs);
        for _ in 0..n_outputs {
            nodes.insert(self.node_innovation_counter.next().unwrap(),
                         NodeGene { node_type: NodeType::Output });
        }
        assert!(nodes.len() == n_inputs + n_outputs);
        NetworkGenome {
            link_genes: InnovationContainer::new(),
            node_genes: nodes,
        }
    }
}
<commit_msg>Simplify<commit_after>use super::innovation::{Innovation, InnovationContainer};
use super::traits::{Distance, Genotype};
use super::alignment::Alignment;
use std::cmp;
use super::crossover::Crossover;
use rand::Rng;
use fixedbitset::FixedBitSet;
use std::collections::BTreeMap;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum NodeType {
    Input,
    Output,
    Hidden,
}

impl Default for NodeType {
    fn default() -> Self {
        NodeType::Hidden
    }
}

#[derive(Debug, Clone)]
pub struct NodeGene {
    pub node_type: NodeType,
}

// To avoid node collisions we use Innovation numbers instead of node
// ids.
#[derive(Debug, Clone)]
pub struct LinkGene {
    // This points to the NodeGene of that innovation
    pub source_node_gene: Innovation,
    // This points to the NodeGene of that innovation
    pub target_node_gene: Innovation,
    pub weight: f64,
    pub active: bool,
}

impl LinkGene {
    pub fn disable(&mut self) {
        assert!(self.active);
        self.active = false;
    }
}

#[derive(Debug, Clone)]
pub struct NetworkGenome {
    pub link_genes: InnovationContainer<LinkGene>,
    pub node_genes: InnovationContainer<NodeGene>,
}

#[derive(Debug, Clone)]
struct AdjMatrix {
    n: usize,
    m: FixedBitSet,
}

impl AdjMatrix {
    fn new(n: usize) -> AdjMatrix {
        AdjMatrix {
            n: n,
            m: FixedBitSet::with_capacity(n * n),
        }
    }

    fn set(&mut self, i: usize, j: usize) {
        self.m.insert(i * self.n + j);
    }

    fn contains(&self, i: usize, j: usize) -> bool {
        self.m.contains(i * self.n + j)
    }

    /// This is O(n**4) in worst case.
    /// XXX: This needs a test for correctness
    fn transitive_closure(mut self) -> AdjMatrix {
        loop {
            let mut counts = 0;
            for i in 0..self.n {
                for j in 0..self.n {
                    if self.contains(i, j) {
                        // look column for j
                        for k in 0..self.n {
                            if self.contains(j, k) {
                                if !self.contains(i, k) {
                                    self.set(i, k);
                                    counts += 1;
                                }
                            }
                        }
                    }
                }
            }
            if counts == 0 {
                break;
            }
        }
        self
    }

    fn unconnected_pairs_no_cycle(&self) -> Vec<(usize, usize)> {
        let mut pairs = Vec::new();
        for i in 0..self.n {
            for j in 0..self.n {
                if i != j {
                    if !(self.contains(i, j) || self.contains(j, i)) {
                        // make sure we don't introduce a cycle
                        pairs.push((i, j));
                    }
                }
            }
        }
        pairs
    }
}

impl NetworkGenome {
    // Uses the crossover method C to recombine left and right.
    pub fn crossover<R: Rng, C: Crossover>(left: &Self, right: &Self, c: &C, rng: &mut R) -> Self {
        let new_link_genes = c.crossover(&left.link_genes, &right.link_genes, rng);
        let mut new_node_genes = c.crossover(&left.node_genes, &right.node_genes, rng);

        // Additionally make sure that all link genes have a correspondant node gene.
        // We do this also for disabled links!
        for link in new_link_genes.map.values() {
            new_node_genes.insert_from_either_or(link.source_node_gene,
                                                 &left.node_genes,
                                                 &right.node_genes);
            new_node_genes.insert_from_either_or(link.target_node_gene,
                                                 &left.node_genes,
                                                 &right.node_genes);
        }

        NetworkGenome {
            link_genes: new_link_genes,
            node_genes: new_node_genes,
        }
    }

    /// Constructs the adjacency matrix from the genome.
    fn adjacency_matrix(&self) -> (AdjMatrix, Vec<Innovation>) {
        // map the node innovation to the index in the adjacency matrix
        let mut map_to_indices: BTreeMap<Innovation, usize> = BTreeMap::new();
        // and the reverse map from index to Innovation
        let mut rev_map: Vec<Innovation> = Vec::new();

        for &node_innov in self.node_genes.map.keys() {
            let next_idx = rev_map.len();
            rev_map.push(node_innov);
            let prev = map_to_indices.insert(node_innov, next_idx);
            assert!(prev.is_none());
        }

        assert!(rev_map.len() == map_to_indices.len());

        let n = map_to_indices.len();
        let mut adj_matrix = AdjMatrix::new(n);
        for link in self.link_genes.map.values() {
            if link.active {
                adj_matrix.set(map_to_indices[&link.source_node_gene],
                               map_to_indices[&link.target_node_gene]);
            }
        }

        (adj_matrix, rev_map)
    }

    /// Returns a random link gene innovation which is active. Or None if no such exists.
    pub fn find_random_active_link_gene<R: Rng>(&self, rng: &mut R) -> Option<Innovation> {
        let mut all_active_link_innovations = Vec::with_capacity(self.link_genes.len());
        for (&innov, link) in self.link_genes.map.iter() {
            if link.active {
                all_active_link_innovations.push(innov);
            }
        }
        rng.choose(&all_active_link_innovations).map(|&i| i)
    }

    /// Returns two node innvovations which are not yet connected and which does not
    /// create a cycle. Return `None` if no such connection exists.
    pub fn find_random_unconnected_pair<R: Rng>(&self,
                                                rng: &mut R)
                                                -> Option<(Innovation, Innovation)> {
        // Construct binary adjacency matrix
        let (adj_matrix, rev_map) = self.adjacency_matrix();

        // Construct an array of all currently unconnected nodes.
        let unconnected = adj_matrix.transitive_closure().unconnected_pairs_no_cycle();

        // Out of all unconnected pairs, choose a random one.
        rng.choose(&unconnected).map(|&(source, target)| {
            // reverse map src and target to the node innovation
            (rev_map[source], rev_map[target])
        })
    }
}

impl Genotype for NetworkGenome {}

struct LinkGeneWeightDistance;

impl Distance<LinkGene> for LinkGeneWeightDistance {
    fn distance(&self, a: &LinkGene, b: &LinkGene) -> f64 {
        a.weight - b.weight
    }
}

pub struct LinkGeneListDistance {
    pub excess: f64,
    pub disjoint: f64,
    pub weight: f64,
}

impl Distance<InnovationContainer<LinkGene>> for LinkGeneListDistance {
    fn distance(&self,
                genes_left: &InnovationContainer<LinkGene>,
                genes_right: &InnovationContainer<LinkGene>)
                -> f64 {
        let max_len = cmp::max(genes_left.len(), genes_right.len());
        if max_len == 0 {
            return 0.0;
        }

        let mut matching = 0;
        let mut disjoint = 0;
        let mut excess = 0;
        let mut weight_dist = 0.0;

        genes_left.align(genes_right,
                         &mut |_, alignment| {
                             match alignment {
                                 Alignment::Match(gene_left, gene_right) => {
                                     matching += 1;
                                     weight_dist += LinkGeneWeightDistance.distance(gene_left,
                                                                                gene_right)
                                                                          .abs();
                                 }
                                 Alignment::DisjointLeft(_) | Alignment::DisjointRight(_) => {
                                     disjoint += 1;
                                 }
                                 Alignment::ExcessLeft(_) | Alignment::ExcessRight(_) => {
                                     excess += 1;
                                 }
                             }
                         });

        assert!(2 * matching + disjoint + excess == genes_left.len() + genes_right.len());

        self.excess * (excess as f64) / (max_len as f64) +
        self.disjoint * (disjoint as f64) / (max_len as f64) +
        self.weight *
        if matching > 0 {
            weight_dist / (matching as f64)
        } else {
            0.0
        }
    }
}

pub struct NetworkGenomeDistance {
    pub l: LinkGeneListDistance,
}

impl Distance<NetworkGenome> for NetworkGenomeDistance {
    fn distance(&self, genome_left: &NetworkGenome, genome_right: &NetworkGenome) -> f64 {
        self.l.distance(&genome_left.link_genes, &genome_right.link_genes)
    }
}

pub struct Environment {
    node_innovation_counter: Innovation,
    link_innovation_counter: Innovation,
    // (src_node, target_node) -> link_innovation
    link_innovation_cache: BTreeMap<(Innovation, Innovation), Innovation>,
}

impl Environment {
    pub fn new() -> Environment {
        Environment {
            node_innovation_counter: Innovation::new(0),
            link_innovation_counter: Innovation::new(0),
            link_innovation_cache: BTreeMap::new(),
        }
    }

    // XXX
    fn random_link_weight<R: Rng>(&mut self, rng: &mut R) -> f64 {
        // XXX Choose a weight between -1 and 1?
        rng.gen()
    }

    fn add_link<R: Rng>(&mut self,
                        genome: &mut NetworkGenome,
                        source_node: Innovation,
                        target_node: Innovation,
                        rng: &mut R) {
        let link_gene = LinkGene {
            source_node_gene: source_node,
            target_node_gene: target_node,
            weight: self.random_link_weight(rng),
            active: true,
        };
        self.add_link_gene(genome, link_gene);
    }

    fn add_link_gene(&mut self, genome: &mut NetworkGenome, link_gene: LinkGene) {
        let link_innovation = self.get_link_innovation(link_gene.source_node_gene,
                                                       link_gene.target_node_gene);
        genome.link_genes.insert_or_replace(link_innovation, link_gene);
    }

    fn get_link_innovation(&mut self,
                           source_node_gene: Innovation,
                           target_node_gene: Innovation)
                           -> Innovation {
        let key = (source_node_gene, target_node_gene);
        if let Some(&cached_innovation) = self.link_innovation_cache.get(&key) {
            return cached_innovation;
        }
        let new_innovation = self.link_innovation_counter.next().unwrap();
        self.link_innovation_cache.insert(key, new_innovation);
        new_innovation
    }

    pub fn mutate_add_connection<R: Rng>(&mut self,
                                         genome: &NetworkGenome,
                                         rng: &mut R)
                                         -> Option<NetworkGenome> {
        genome.find_random_unconnected_pair(rng).map(|(src, target)| {
            let mut offspring = genome.clone();
            // Add new link to the offspring genome
            self.add_link(&mut offspring, src, target, rng);
            offspring
        })
    }

    /// choose a random link. split it in half.
    pub fn mutate_add_node<R: Rng>(&mut self,
                                   genome: &NetworkGenome,
                                   rng: &mut R)
                                   -> Option<NetworkGenome> {
        genome.find_random_active_link_gene(rng).map(|link_innov| {
            // split link in half.
            let mut offspring = genome.clone();
            let new_node_innovation = self.new_node_innovation();
            // add new node
            offspring.node_genes.insert(new_node_innovation,
                                        NodeGene { node_type: NodeType::Hidden });
            // disable `link_innov` in offspring
            // we keep this gene (but disable it), because this allows us to have a structurally
            // compatible genome to the old one, as disabled genes are taken into account for
            // the genomic distance measure.
            offspring.link_genes.get_mut(&link_innov).unwrap().disable();
            // add two new link innovations with the new node in the middle.
            // XXX: Choose random weights? Or split weight? We use random weights for now.
            let (orig_src_node, orig_target_node) = {
                let orig_link = offspring.link_genes.get(&link_innov).unwrap();
                (orig_link.source_node_gene, orig_link.target_node_gene)
            };
            self.add_link(&mut offspring, orig_src_node, new_node_innovation, rng);
            self.add_link(&mut offspring, new_node_innovation, orig_target_node, rng);
            offspring
        })
    }

    fn new_node_innovation(&mut self) -> Innovation {
        self.node_innovation_counter.next().unwrap()
    }

    // Generates a NetworkGenome with `n_inputs` input nodes and `n_outputs` output nodes.
    // The genome will not have any link nodes.
    pub fn generate_genome(&mut self, n_inputs: usize, n_outputs: usize) -> NetworkGenome {
        assert!(n_inputs > 0 && n_outputs > 0);
        let mut nodes = InnovationContainer::new();
        for _ in 0..n_inputs {
            nodes.insert(self.node_innovation_counter.next().unwrap(),
                         NodeGene { node_type: NodeType::Input });
        }
        assert!(nodes.len() == n_inputs);
        for _ in 0..n_outputs {
            nodes.insert(self.node_innovation_counter.next().unwrap(),
                         NodeGene { node_type: NodeType::Output });
        }
        assert!(nodes.len() == n_inputs + n_outputs);
        NetworkGenome {
            link_genes: InnovationContainer::new(),
            node_genes: nodes,
        }
    }
}
<|endoftext|>


<commit_before>use types::{OscPacket, OscType, OscResult, OscMessage, OscBundle};
use errors::OscError;
use utils;

use std::io;
use std::io::{Read, BufRead};

use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8]) -> OscResult<OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(OscError::BadPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let addr: String = try!(read_osc_string(&mut cursor));
    let type_tags: String = try!(read_osc_string(&mut cursor));

    if type_tags.len() > 1 {
        let args: Vec<OscType> = try!(read_osc_args(&mut cursor, type_tags));

        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: Some(args),
        }))
    } else {
        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: None,
        }))
    }
}

fn decode_bundle(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let b = try!(read_osc_string(&mut cursor));
    if b != "bundle" {
        return Err(OscError::BadBundle);
    }

    let time_tag = try!(read_time_tag(&mut cursor));
    let mut bundle: Vec<OscPacket> = Vec::new();
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                                 .map_err(OscError::ByteOrderError)) as usize;
    let mut buf: Vec<u8> = Vec::new();
    let cnt: usize = try!(cursor.take(size as u64)
                                .read_to_end(&mut buf)
                                .map_err(OscError::ReadError));
    if cnt == size {
        try!(decode(&mut buf).map(|p| bundle.push(p)));
    } else {
        return Err(OscError::BadBundle);
    }

    Ok(OscPacket::Bundle(OscBundle {
        timetag: time_tag,
        content: bundle,
    }))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    try!(cursor.read_until(0, &mut str_buf)
               .map_err(OscError::ReadError)); // ignore returned byte count
    pad_cursor(cursor);
    // convert to String and remove nul bytes
    String::from_utf8(str_buf)
        .map_err(|e| OscError::StringError(e))
        .map(|s| {
            s.trim_matches(0u8 as char)
             .to_string()
        })
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> OscResult<Vec<OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();
    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        let arg: OscType = try!(read_osc_arg(cursor, tag));
        args.push(arg);
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> OscResult<OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(OscType::Float)
                  .map_err(OscError::ByteOrderError)
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(OscType::Double)
                  .map_err(OscError::ByteOrderError)
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(OscType::Int)
                  .map_err(OscError::ByteOrderError)
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(OscType::Long)
                  .map_err(OscError::ByteOrderError)
        }
        's' => {
            read_osc_string(cursor).map(|s| OscType::String(s))
        }
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(OscType::Blob(buf)),
                        Err(e) => Err(OscError::ReadError(e)),
                    }
                }
                // TODO: use correct error type
                Err(e) => return Err(OscError::BadBundle),
            }
        }
        _ => Err(OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> OscResult<OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(OscType::Time(date, frac)),
                Err(e) => Err(OscError::ByteOrderError(e)),
            }
        }
        Err(e) => Err(OscError::ByteOrderError(e)),
    }
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<commit_msg>Refactor reading of byte blob arguments<commit_after>use types::{OscPacket, OscType, OscResult, OscMessage, OscBundle};
use errors::OscError;
use utils;

use std::io;
use std::io::{Read, BufRead};

use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8]) -> OscResult<OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(OscError::BadPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let addr: String = try!(read_osc_string(&mut cursor));
    let type_tags: String = try!(read_osc_string(&mut cursor));

    if type_tags.len() > 1 {
        let args: Vec<OscType> = try!(read_osc_args(&mut cursor, type_tags));

        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: Some(args),
        }))
    } else {
        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: None,
        }))
    }
}

fn decode_bundle(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let b = try!(read_osc_string(&mut cursor));
    if b != "bundle" {
        return Err(OscError::BadBundle);
    }

    let time_tag = try!(read_time_tag(&mut cursor));
    let mut bundle: Vec<OscPacket> = Vec::new();
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                                 .map_err(OscError::ByteOrderError)) as usize;
    let mut buf: Vec<u8> = Vec::new();
    let cnt: usize = try!(cursor.take(size as u64)
                                .read_to_end(&mut buf)
                                .map_err(OscError::ReadError));
    if cnt == size {
        try!(decode(&mut buf).map(|p| bundle.push(p)));
    } else {
        return Err(OscError::BadBundle);
    }

    Ok(OscPacket::Bundle(OscBundle {
        timetag: time_tag,
        content: bundle,
    }))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    try!(cursor.read_until(0, &mut str_buf)
               .map_err(OscError::ReadError)); // ignore returned byte count
    pad_cursor(cursor);
    // convert to String and remove nul bytes
    String::from_utf8(str_buf)
        .map_err(|e| OscError::StringError(e))
        .map(|s| {
            s.trim_matches(0u8 as char)
             .to_string()
        })
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> OscResult<Vec<OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();
    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        let arg: OscType = try!(read_osc_arg(cursor, tag));
        args.push(arg);
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> OscResult<OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(OscType::Float)
                  .map_err(OscError::ByteOrderError)
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(OscType::Double)
                  .map_err(OscError::ByteOrderError)
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(OscType::Int)
                  .map_err(OscError::ByteOrderError)
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(OscType::Long)
                  .map_err(OscError::ByteOrderError)
        }
        's' => {
            read_osc_string(cursor).map(|s| OscType::String(s))
        }
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            let size: usize =
                try!(cursor.read_u32::<BigEndian>()
                           .map_err(OscError::ByteOrderError)) as usize;
            let mut byte_buf: Vec<u8> = Vec::with_capacity(size);

            try!(cursor.take(size as u64)
                       .read(&mut byte_buf)
                       .map(|_| Ok(OscType::Blob(byte_buf)))
                       .map_err(OscError::ReadError))

        }
        _ => Err(OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> OscResult<OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(OscType::Time(date, frac)),
                Err(e) => Err(OscError::ByteOrderError(e)),
            }
        }
        Err(e) => Err(OscError::ByteOrderError(e)),
    }
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::io;
use std::io::Cursor;
use std::fs;
use std::fs::File;
use std::path::Path;
use std::rc::Rc;

use byteorder::{LittleEndian, ReadBytesExt};
use digest::digest_reader;
use filebuffer::FileBuffer;
use sha2::Sha256;

use routing::EffectId;

/// Resource manager. Where to search for various file types (e.g. Effects).
/// Uses a 'dumb' implementation - doesn't try to auto-configure paths (/usr/bin/share/[...],
/// ~/.friendship, etc). Instead, designed to be configured by the host.
#[derive(Default, Debug)]
pub struct ResMan {
    dirs: Vec<PathBuf>,
}

/// Audio that may be on-disk.
#[derive(Clone, Debug)]
pub struct AudioBuffer {
    buffer: Rc<FileBuffer>,
}

impl ResMan {
    pub fn new() -> Self {
        Default::default()
    }
    pub fn add_dir(&mut self, dir: PathBuf) {
        self.dirs.push(dir);
    }
    /// Returns all definitions of the given effect in the form of an iterator
    ///   over boxed objects implementing io::Read.
    pub fn find_effect<'a>(&'a self, id: &'a EffectId) -> impl Iterator<Item=(PathBuf, File)> + 'a {
        self.iter_effect_files(id).map(|path| {
            (path.clone(), File::open(path).unwrap())
        })
    }
    fn iter_effect_files<'a>(&'a self, id: &'a EffectId) -> impl Iterator<Item=PathBuf> + 'a {
        self.iter_all_files().filter(move |f| {
            let did_match = match *id.sha256() {
                None => true,
                Some(ref hash) => {
                    let mut file = File::open(f).unwrap();
                    let result = digest_reader::<Sha256>(&mut file).unwrap();
                    hash == result.as_slice()
                }
            };
            trace!("Resman: testing hash for: {:?} ({:?})", f, did_match);
            did_match
        })
    }
    fn iter_all_files<'a>(&'a self) -> impl Iterator<Item=PathBuf> + 'a {
        // dirs as PathBuf -> valid ReadDir objects
        self.dirs.iter().filter_map(|dir_path| {
            fs::read_dir(dir_path)
                .map_err(|e| warn!("ResMan: Failed to read directory {:?}: {}", dir_path, e))
                .ok()
        })
        // ReadDir objects -> flat list of Result<DirEntry>
        .flat_map(|read_dir| {
            read_dir
        })
        // Result<DirEntry> -> DirEntry
        .filter_map(|dir_entry| {
            dir_entry
                .map_err(|e| warn!("ResMan: Failed to read directory entry: {}", e))
                .ok()
        })
        // keep only the files
        .filter(|dir_entry| {
            if let Ok(file_type)=dir_entry.file_type() {
                file_type.is_file()
            } else {
                false
            }
        })
        // DirEntry -> Path
        .map(|dir_entry| {
            dir_entry.path()
        })
    }
}

impl AudioBuffer {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
        if path.as_ref().extension().map(|e| e == "f32").unwrap_or(false) {
            // TODO: don't abort on failure; instead, treat as zero stream
            Ok(Self {
                buffer: Rc::new(FileBuffer::open(path)?)
            })
        } else {
            Err(io::Error::new(io::ErrorKind::Other, format!("Unknown audio format for file: {:?}", path.as_ref())))
        }
    }
    /// Read data from the buffer.
    pub fn get(&self, idx: u64, ch: u32) -> f32 {
        assert_eq!(ch, 0);
        // TODO: this isn't very dependable for 32-bit OSes.
        let idx = idx*4; // frame index -> byte index
        let view = &self.buffer[idx as usize..idx as usize + 4];
        let mut reader = Cursor::new(view);
        // Read float or 0f32 if error (e.g. end of file?)
        reader.read_f32::<LittleEndian>().unwrap_or(0f32)
    }
}
<commit_msg>Cache sha -> path for ResMan<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io;
use std::io::Cursor;
use std::path::{Path, PathBuf};
use std::rc::Rc;

use byteorder::{LittleEndian, ReadBytesExt};
use digest::digest_reader;
use filebuffer::FileBuffer;
use sha2::Sha256;

use routing::EffectId;

/// Resource manager. Where to search for various file types (e.g. Effects).
/// Uses a 'dumb' implementation - doesn't try to auto-configure paths (/usr/bin/share/[...],
/// ~/.friendship, etc). Instead, designed to be configured by the host.
#[derive(Default, Debug)]
pub struct ResMan {
    /// List of directories to search for files in.
    dirs: Vec<PathBuf>,
    /// Object that handles indexing/caching files.
    cache: RefCell<ResCache>,
}

/// Audio that may be on-disk.
#[derive(Clone, Debug)]
pub struct AudioBuffer {
    buffer: Rc<FileBuffer>,
}

#[derive(Default, Debug)]
struct ResCache {
    /// Map sha's to paths.
    sha256_to_path: HashMap<[u8; 32], PathBuf>,
}

impl ResMan {
    pub fn new() -> Self {
        Default::default()
    }
    pub fn add_dir(&mut self, dir: PathBuf) {
        self.dirs.push(dir);
    }
    /// Returns all definitions of the given effect in the form of an iterator
    ///   over boxed objects implementing io::Read.
    pub fn find_effect<'a>(&'a self, id: &'a EffectId) -> impl Iterator<Item=(PathBuf, File)> + 'a {
        self.iter_effect_files(id).map(|path| {
            (path.clone(), File::open(path).unwrap())
        })
    }
    fn iter_effect_files<'a>(&'a self, id: &'a EffectId) -> impl Iterator<Item=PathBuf> + 'a {
        self.iter_all_files(id.sha256().as_ref()).filter(move |f| {
            let did_match = match *id.sha256() {
                None => true,
                Some(ref hash) => {
                    let mut file = File::open(f).unwrap();
                    // TODO: the hash could still change between now and when we parse the file!
                    let result = digest_reader::<Sha256>(&mut file).unwrap();
                    // Cache this sha256->file relationship.
                    self.cache.borrow_mut().notify_sha256(f.clone(), slice_to_array32(result.as_slice()));
                    hash == result.as_slice()
                }
            };
            trace!("Resman: testing hash for: {:?} ({:?})", f, did_match);
            did_match
        })
    }
    /// Iterates over all files.
    /// Files with matching search criteria are iterated first.
    /// Files may be visited multiple times. This happens if their sha matches the hint.
    fn iter_all_files<'a>(&'a self, sha256_hint: Option<&[u8; 32]>) -> impl Iterator<Item=PathBuf> + 'a {
        let prioritized = sha256_hint
            .and_then(|sha| self.cache.borrow().get_path_by_sha256(sha).cloned())
            .into_iter();
        // dirs as PathBuf -> valid ReadDir objects
        let all_files = self.dirs.iter().filter_map(|dir_path| {
            fs::read_dir(dir_path)
                .map_err(|e| warn!("ResMan: Failed to read directory {:?}: {}", dir_path, e))
                .ok()
        })
        // ReadDir objects -> flat list of Result<DirEntry>
        .flat_map(|read_dir| {
            read_dir
        })
        // Result<DirEntry> -> DirEntry
        .filter_map(|dir_entry| {
            dir_entry
                .map_err(|e| warn!("ResMan: Failed to read directory entry: {}", e))
                .ok()
        })
        // keep only the files
        .filter(|dir_entry| {
            if let Ok(file_type)=dir_entry.file_type() {
                file_type.is_file()
            } else {
                false
            }
        })
        // DirEntry -> Path
        .map(|dir_entry| {
            dir_entry.path()
        });
        prioritized.chain(all_files)
    }
}

impl AudioBuffer {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
        if path.as_ref().extension().map(|e| e == "f32").unwrap_or(false) {
            // TODO: don't abort on failure; instead, treat as zero stream
            Ok(Self {
                buffer: Rc::new(FileBuffer::open(path)?)
            })
        } else {
            Err(io::Error::new(io::ErrorKind::Other, format!("Unknown audio format for file: {:?}", path.as_ref())))
        }
    }
    /// Read data from the buffer.
    pub fn get(&self, idx: u64, ch: u32) -> f32 {
        assert_eq!(ch, 0);
        // TODO: this isn't very dependable for 32-bit OSes.
        let idx = idx*4; // frame index -> byte index
        let view = &self.buffer[idx as usize..idx as usize + 4];
        let mut reader = Cursor::new(view);
        // Read float or 0f32 if error (e.g. end of file?)
        reader.read_f32::<LittleEndian>().unwrap_or(0f32)
    }
}

impl ResCache {
    /// Call upon discovery of a file's hash.
    fn notify_sha256(&mut self, path: PathBuf, sha256: [u8; 32]) {
        self.sha256_to_path.insert(sha256, path);
    }
    /// Attempt to look up a file by its hash.
    fn get_path_by_sha256(&self, sha256: &[u8; 32]) -> Option<&PathBuf> {
        self.sha256_to_path.get(sha256)
    }
}

/// Create a 32-entry array from a slice.
fn slice_to_array32(slice: &[u8]) -> [u8; 32] {
    let mut ret: [u8; 32] = Default::default();
    ret.copy_from_slice(slice);
    ret
}
<|endoftext|>


<commit_before>use format::field::*;
use nom::{be_u8,be_u16,be_u32,be_u64};

pub const DESCRIPTION: &'static str = "{{name}} - {{major_version}}.{{minor_version}}.{{revision}}";

pub enum Class {
  {{#each specs.classes as |class| ~}}
    {{camel class.name}}({{camel class.name}}Methods),
  {{/each ~}}
  None,
}

macro_rules! call_path (
  ($i: expr, $p: path) => ($p($i))
);

named!(pub parse_class<Class>,
  switch!(be_u16,
  {{#each specs.classes as |class| ~}}
    {{class.id}} => call!(parse_class_{{snake class.name}}) |
  {{/each ~}}
  _ => value!(Class::None)
  )
);

{{#each specs.classes as |class|}}
  pub enum {{camel class.name}}Methods {
    {{#each class.methods as |method| ~}}
      {{camel method.name}}({{camel class.name}}{{camel method.name}}),
    {{/each ~}}
    None,
  }

  named!(pub parse_class_{{snake class.name}}<Class>,
    switch!(be_u16,
      {{#each class.methods as |method| ~}}
      {{method.id}} => map!(call!(parse_class_{{snake class.name}}_method_{{snake method.name}}), |m| Class::{{camel class.name}}(m)) |
      {{/each ~}}
      _  =>  value!(Class::{{camel class.name}}({{camel class.name}}Methods::None))
    )
  );

  {{#each class.methods as |method|}}
    pub struct {{camel class.name}}{{camel method.name}} {
      {{#each method.arguments as |argument| ~}}
        pub {{snake argument.name}}: {{map_type argument}},
      {{/each ~}}

    }

    named!(parse_class_{{snake class.name}}_method_{{snake method.name}}<{{camel class.name}}Methods>,
      do_parse!(
        {{#each method.arguments as |argument| ~}}
          {{snake argument.name}}: {{map_parser argument}} >>
        {{/each ~}}

        ({{camel class.name}}Methods::{{camel method.name}}({{camel class.name}}{{camel method.name}} {
          {{#each method.arguments as |argument| ~}}
            {{snake argument.name}}: {{snake argument.name}},
          {{/each ~}}
        }))
      )
    );
  {{/each}}
{{/each}}
<commit_msg>use modules<commit_after>use format::field::*;
use nom::{be_u8,be_u16,be_u32,be_u64};

pub const DESCRIPTION: &'static str = "{{name}} - {{major_version}}.{{minor_version}}.{{revision}}";

pub enum Class {
  {{#each specs.classes as |class| ~}}
    {{camel class.name}}({{snake class.name}}::Methods),
  {{/each ~}}
  None,
}

macro_rules! call_path (
  ($i: expr, $p: path) => ($p($i))
);

named!(pub parse_class<Class>,
  switch!(be_u16,
  {{#each specs.classes as |class| ~}}
    {{class.id}} => call_path!({{snake class.name}}::parse) |
  {{/each ~}}
  _  => value!(Class::None)
  )
);

{{#each specs.classes as |class|}}
  pub mod {{snake class.name}} {
    use super::Class;
    use format::field::*;
    use nom::{be_u8,be_u16,be_u32,be_u64};

    pub enum Methods {
      {{#each class.methods as |method| ~}}
        {{camel method.name}}({{camel method.name}}),
      {{/each ~}}
      None,
    }

    named!(pub parse<Class>,
      switch!(be_u16,
        {{#each class.methods as |method| ~}}
        {{method.id}} => map!(call!(parse_{{snake method.name}}), |m| Class::{{camel class.name}}(m)) |
        {{/each ~}}
        _  => value!(Class::{{camel class.name}}(Methods::None))
      )
    );

    {{#each class.methods as |method|}}
      pub struct {{camel method.name}} {
        {{#each method.arguments as |argument| ~}}
          pub {{snake argument.name}}: {{map_type argument}},
        {{/each ~}}

      }

      named!(parse_{{snake method.name}}<Methods>,
        do_parse!(
          {{#each method.arguments as |argument| ~}}
            {{snake argument.name}}: {{map_parser argument}} >>
          {{/each ~}}

          (Methods::{{camel method.name}}({{camel method.name}} {
            {{#each method.arguments as |argument| ~}}
              {{snake argument.name}}: {{snake argument.name}},
            {{/each ~}}
          }))
        )
      );
    {{/each}}
  }
{{/each}}
<|endoftext|>