<commit_before>/**
 *   Mles Asynchronous Server
 *
 *   Copyright (C) 2017  Mles developers
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
extern crate tokio_core;
extern crate futures;
extern crate mles_utils;

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter;
use std::io::{Error, ErrorKind};
use std::{process, env};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use tokio_core::net::TcpListener;
//use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_core::io::{self, Io};

use futures::Future;
use futures::stream::{self, Stream};
use futures::sync::mpsc::unbounded;
use mles_utils::*;

const HDRL: usize = 4; //hdr len
const KEYL: usize = 8; //key len

fn main() {
    let mut peer = "".to_string();
    let mut argcnt = 0;
    for arg in env::args() {
        argcnt += 1;
        if 2 == argcnt {
            peer = arg;
            peer += ":8077";
            match peer.parse::<SocketAddr>() {
                Ok(_) => {},
                    Err(err) => {
                        println!("Error: {}\nUsage: mles [peer-address]", err);
                        process::exit(1);
                    },
            }
        }
        if argcnt > 2 {
            println!("Usage: mles [peer-address]");
            process::exit(1);
        }
    }

    /* TODO: add peer connection */
    let _peer = match peer.parse::<SocketAddr>() {
        Ok(addr) => addr,
        Err(_) => {
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
        },
    };

    let address = "0.0.0.0:8077";
    let address = address.parse().unwrap();

    let keyval = match env::var("MLES_KEY") {
        Ok(val) => val,
        Err(_) => "".to_string(),
    };

    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let socket = match TcpListener::bind(&address, &handle) {
        Ok(listener) => listener,
        Err(err) => {
            println!("Error: {}", err);
            process::exit(1);
        },
    };
    println!("Listening on: {}", address);

    let spawned = Rc::new(RefCell::new(HashMap::new()));
    let channelmsgs = Rc::new(RefCell::new(HashMap::new()));
    let mut cnt = 0;

    let srv = socket.incoming().for_each(move |(stream, addr)| {
        println!("New Connection: {}", addr);
        let paddr = match stream.peer_addr() {
                Ok(paddr) => paddr,
                Err(_) => {
                    let addr = "0.0.0.0:0";
                    let addr = addr.parse::<SocketAddr>().unwrap();
                    addr
                }
        };

        let (reader, writer) = stream.split();

        let (tx, rx) = unbounded();
        cnt += 1;

        let frame = io::read_exact(reader, vec![0;HDRL]);
        let frame = frame.and_then(move |(reader, payload)| {
            if payload.len() == 0 {
                Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
            } else {
                if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                }
                let hdr_len = read_hdr_len(payload.as_slice());
                if 0 == hdr_len {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                }
                Ok((reader, hdr_len))
            }
        });

        let paddr_inner = paddr.clone();
        let keyval_inner = keyval.clone();
        let frame = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;KEYL]);
            // verify key
            let tframe = tframe.and_then(move |(reader, key)| {
                let hkey;
                let key = read_key(key);
                if 0 == keyval_inner.len() {
                    hkey = do_hash(&paddr_inner);
                }
                else {
                    hkey = do_hash(&keyval_inner);
                }
                if hkey != key {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect remote key"));
                }
                Ok((reader, hdr_len))
            });
            tframe
        });

        let tx_once = tx.clone();
        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_once = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;hdr_len]);
            let tframe = tframe.and_then(move |(reader, message)| {
                if 0 == message.len() {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                }
                else {
                    let mut spawned_once = spawned_inner.borrow_mut();
                    let mut chanmsgs_once = chanmsgs_inner.borrow_mut();
                    let decoded_message = message_decode(message.as_slice());
                    let channel = decoded_message.channel.clone();
                    if !spawned_once.contains_key(&channel) {
                        let mut channel_entry = HashMap::new();
                        channel_entry.insert(cnt, tx_once);
                        spawned_once.insert(channel.clone(), channel_entry);

                        let messages: Vec<Vec<u8>> = Vec::new();
                        chanmsgs_once.insert(channel.clone(), messages);
                    }
                    else {
                        let mut channel_entry = spawned_once.get_mut(&channel).unwrap();
                        channel_entry.insert(cnt, tx_once);
                        let chanmsgs = chanmsgs_once.get(&channel).unwrap();
                        for msg in chanmsgs {
                            tx.send(msg.clone()).unwrap();
                        }
                    }
                    println!("User {}:{} joined channel {}", cnt, decoded_message.uid, channel);
                    /* TODO: add peer connection */
                    Ok((reader, channel))
                }
            });
            tframe
        });

        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_next = socket_once.and_then(move |(reader, channel)| {
            let channel_next = channel.clone();
            let iter = stream::iter(iter::repeat(()).map(Ok::<(), Error>));
            iter.fold(reader, move |reader, _| {
                let frame = io::read_exact(reader, vec![0;HDRL]);
                let frame = frame.and_then(move |(reader, payload)| {
                    if payload.len() == 0 {
                        Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
                    } else {
                        if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                        }
                        let hdr_len = read_hdr_len(payload.as_slice());
                        if 0 == hdr_len {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                        }
                        Ok((reader, payload, hdr_len))
                    }
                });

                let frame = frame.and_then(move |(reader, hdr, hdr_len)| {
                    //dummy read key
                    let tframe = io::read_exact(reader, vec![0;KEYL]);
                    let tframe = tframe.and_then(move |(reader, key)| {
                        Ok((reader, hdr, key, hdr_len))
                    });
                    tframe
                });

                let frame = frame.and_then(move |(reader, hdr, key, hdr_len)| {
                    let tframe = io::read_exact(reader, vec![0;hdr_len]);
                    let tframe = tframe.and_then(move |(reader, message)| {
                        if 0 == message.len() {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                        }
                        else {
                            Ok((reader, hdr, key, message))
                        }
                    });
                    tframe
                });

                let spawned = spawned_inner.clone();
                let chanmsgs = chanmsgs_inner.clone();
                let channel = channel_next.clone();
                frame.map(move |(reader, mut hdr, mut key, message)| {
                    key.extend(message);
                    hdr.extend(key);

                    // add to history
                    let mut channel_msgs = chanmsgs.borrow_mut();
                    let mut channel_msg = channel_msgs.get_mut(&channel).unwrap();
                    channel_msg.push(hdr.clone());

                    //distribute
                    let spawned = spawned.borrow();
                    let channels = spawned.get(&channel).unwrap();
                    for (ocnt, tx) in channels {
                        if *ocnt != cnt {
                            tx.send(hdr.clone()).unwrap();
                        }
                    }
                    reader
                })
            })
        });

        let socket_writer = rx.fold(writer, |writer, msg| {
            let amt = io::write_all(writer, msg);
            let amt = amt.map(|(writer, _)| writer);
            amt.map_err(|_| ())
        });

        let channels = spawned.clone();
        let chanmsgs = channelmsgs.clone();
        let socket_reader = socket_next.map_err(|_| ());
        let connection = socket_reader.map(|_| ()).select(socket_writer.map(|_| ()));
        handle.spawn(connection.then(move |_| {
            let mut chans = channels.borrow_mut();
            for (cname, channel) in chans.iter_mut() {
                if channel.contains_key(&cnt) {
                    channel.remove(&cnt);
                    if 0 == channel.len() {
                        let mut channelmsgs = chanmsgs.borrow_mut();
                        channelmsgs.remove(cname);
                        println!("Channel {} dropped.", cname);
                        drop(channel);
                    }
                    break;
                }
            }
            println!("Connection {} for user {} closed.", addr, cnt);
            Ok(())
        }));
        Ok(())
    });

    // execute server
    core.run(srv).unwrap();
}

<commit_msg>Minor preparations to add peer support.<commit_after>/**
 *   Mles Asynchronous Server
 *
 *   Copyright (C) 2017  Mles developers
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
extern crate tokio_core;
extern crate futures;
extern crate mles_utils;

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter;
use std::io::{Error, ErrorKind};
use std::{process, env};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use tokio_core::net::TcpListener;
//use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_core::io::{self, Io};

use futures::Future;
use futures::stream::{self, Stream};
use futures::sync::mpsc::unbounded;
use mles_utils::*;

const HDRL: usize = 4; //hdr len
const KEYL: usize = 8; //key len

fn main() {
    let mut peer = "".to_string();
    let mut argcnt = 0;
    for arg in env::args() {
        argcnt += 1;
        if 2 == argcnt {
            peer = arg;
            peer += ":8077";
            match peer.parse::<SocketAddr>() {
                Ok(_) => {},
                    Err(err) => {
                        println!("Error: {}\nUsage: mles [peer-address]", err);
                        process::exit(1);
                    },
            }
        }
        if argcnt > 2 {
            println!("Usage: mles [peer-address]");
            process::exit(1);
        }
    }

    let _peer = match peer.parse::<SocketAddr>() {
        Ok(addr) => addr,
        Err(_) => {
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
        },
    };

    let keyval = match env::var("MLES_KEY") {
        Ok(val) => val,
        Err(_) => "".to_string(),
    };

    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let address = "0.0.0.0:8077".parse().unwrap();
    let socket = match TcpListener::bind(&address, &handle) {
        Ok(listener) => listener,
        Err(err) => {
            println!("Error: {}", err);
            process::exit(1);
        },
    };
    println!("Listening on: {}", address);

    let spawned = Rc::new(RefCell::new(HashMap::new()));
    let channelmsgs = Rc::new(RefCell::new(HashMap::new()));
    let mut cnt = 0;

    //connect to peer
    //let tcp = TcpStream::connect(&peer, &handle);
    //let client = tcp.map_err(|_| ()).and_then(|pstream| {
    //    let _val = pstream.set_nodelay(true).map_err(|_| panic!("Cannot set peer to no delay"));
    //    println!("Adding peer {}", cnt);
    //    Ok((pstream))
    //});

    let srv = socket.incoming().for_each(move |(stream, addr)| {
        println!("New Connection: {}", addr);
        let paddr = match stream.peer_addr() {
                Ok(paddr) => paddr,
                Err(_) => {
                    let addr = "0.0.0.0:0";
                    let addr = addr.parse::<SocketAddr>().unwrap();
                    addr
                }
        };
        let _val = stream.set_nodelay(true).map_err(|_| panic!("Cannot set to no delay"));;

        let (reader, writer) = stream.split();

        let (tx, rx) = unbounded();

        cnt += 1;

        let frame = io::read_exact(reader, vec![0;HDRL]);
        let frame = frame.and_then(move |(reader, payload)| {
            if payload.len() == 0 {
                Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
            } else {
                if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                }
                let hdr_len = read_hdr_len(payload.as_slice());
                if 0 == hdr_len {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                }
                Ok((reader, hdr_len))
            }
        });

        let paddr_inner = paddr.clone();
        let keyval_inner = keyval.clone();
        let frame = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;KEYL]);
            // verify key
            let tframe = tframe.and_then(move |(reader, key)| {
                let hkey;
                let key = read_key(key);
                if 0 == keyval_inner.len() {
                    hkey = do_hash(&paddr_inner);
                }
                else {
                    hkey = do_hash(&keyval_inner);
                }
                if hkey != key {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect remote key"));
                }
                Ok((reader, hdr_len))
            });
            tframe
        });

        let tx_once = tx.clone();
        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_once = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;hdr_len]);
            let tframe = tframe.and_then(move |(reader, message)| {
                if 0 == message.len() {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                }
                else {
                    let mut spawned_once = spawned_inner.borrow_mut();
                    let mut chanmsgs_once = chanmsgs_inner.borrow_mut();
                    let decoded_message = message_decode(message.as_slice());
                    let channel = decoded_message.channel.clone();
                    if !spawned_once.contains_key(&channel) {
                        let mut channel_entry = HashMap::new();
                        channel_entry.insert(cnt, tx_once);
                        spawned_once.insert(channel.clone(), channel_entry);

                        let messages: Vec<Vec<u8>> = Vec::new();
                        chanmsgs_once.insert(channel.clone(), messages);
                    }
                    else {
                        let mut channel_entry = spawned_once.get_mut(&channel).unwrap();
                        channel_entry.insert(cnt, tx_once);
                        let chanmsgs = chanmsgs_once.get(&channel).unwrap();
                        for msg in chanmsgs {
                            tx.send(msg.clone()).unwrap();
                        }
                        //TODO try to connect to peer
                    }
                    println!("User {}:{} joined channel {}", cnt, decoded_message.uid, channel);
                    Ok((reader, channel))
                }
            });
            tframe
        });

        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_next = socket_once.and_then(move |(reader, channel)| {
            let channel_next = channel.clone();
            let iter = stream::iter(iter::repeat(()).map(Ok::<(), Error>));
            iter.fold(reader, move |reader, _| {
                let frame = io::read_exact(reader, vec![0;HDRL]);
                let frame = frame.and_then(move |(reader, payload)| {
                    if payload.len() == 0 {
                        Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
                    } else {
                        if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                        }
                        let hdr_len = read_hdr_len(payload.as_slice());
                        if 0 == hdr_len {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                        }
                        Ok((reader, payload, hdr_len))
                    }
                });

                let frame = frame.and_then(move |(reader, hdr, hdr_len)| {
                    //dummy read key
                    let tframe = io::read_exact(reader, vec![0;KEYL]);
                    let tframe = tframe.and_then(move |(reader, key)| {
                        Ok((reader, hdr, key, hdr_len))
                    });
                    tframe
                });

                let frame = frame.and_then(move |(reader, hdr, key, hdr_len)| {
                    let tframe = io::read_exact(reader, vec![0;hdr_len]);
                    let tframe = tframe.and_then(move |(reader, message)| {
                        if 0 == message.len() {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                        }
                        else {
                            Ok((reader, hdr, key, message))
                        }
                    });
                    tframe
                });

                let spawned = spawned_inner.clone();
                let chanmsgs = chanmsgs_inner.clone();
                let channel = channel_next.clone();
                frame.map(move |(reader, mut hdr, mut key, message)| {
                    key.extend(message);
                    hdr.extend(key);

                    // add to history
                    let mut channel_msgs = chanmsgs.borrow_mut();
                    let mut channel_msg = channel_msgs.get_mut(&channel).unwrap();
                    channel_msg.push(hdr.clone());

                    //distribute
                    let spawned = spawned.borrow();
                    let channels = spawned.get(&channel).unwrap();
                    for (ocnt, tx) in channels {
                        if *ocnt != cnt {
                            tx.send(hdr.clone()).unwrap();
                        }
                    }
                    reader
                })
            })
        });

        let socket_writer = rx.fold(writer, |writer, msg| {
            let amt = io::write_all(writer, msg);
            let amt = amt.map(|(writer, _)| writer);
            amt.map_err(|_| ())
        });

        let channels = spawned.clone();
        let chanmsgs = channelmsgs.clone();
        let socket_reader = socket_next.map_err(|_| ());
        let connection = socket_reader.map(|_| ()).select(socket_writer.map(|_| ()));
        handle.spawn(connection.then(move |_| {
            let mut chans = channels.borrow_mut();
            for (cname, channel) in chans.iter_mut() {
                if channel.contains_key(&cnt) {
                    channel.remove(&cnt);
                    if 0 == channel.len() {
                        let mut channelmsgs = chanmsgs.borrow_mut();
                        channelmsgs.remove(cname);
                        println!("Channel {} dropped.", cname);
                        drop(channel);
                    }
                    break;
                }
            }
            println!("Connection {} for user {} closed.", addr, cnt);
            Ok(())
        }));
        Ok(())
    });

    // execute server
    core.run(srv).unwrap();
}

<|endoftext|>


<commit_before>//! A tree represented via a petgraph graph, used for way-cooler's
//! layout.

use petgraph::EdgeDirection;
use petgraph::graph::{Graph, EdgeDirection, Node, Neighbors, NodeIndex};

use layout::{Container, ContainerType};

/// Layout tree implemented with petgraph.
#[derive(Debug)]
pub struct Tree {
    graph: Graph<Container, ()>, // Directed graph
    root: NodeIndex
}

impl Tree {
    /// Creates a new layout tree with a root node.
    pub fn new() -> Tree {
        let mut graph = Graph::new();
        let root_ix = graph.add_node(Container::Root);
        Tree { graph: graph, root: root_it }
    }

    /// Adds a new child to a node at the index, returning the edge index
    /// of their connection and the index of the new node.
    // TODO should this return a result like the old API?
    pub fn add_child(&mut self, parent_ix: NodeIndex, val: Container)
                     -> (EdgeIndex, NodeIndex) {
        let parent = self.graph.node_weight(parent_ix)
            .expect("add_child: parent not found");
        if !parent.get_type().can_have_child(val.get_type()) {
            panic!("Attempted to give a {:?} a {:?} child!",
                   parent.get_type(), child.get_type())
        }
        let child_ix = self.graph.add_node(val);
        let edge_ix = self.graph.update_edge(parent_ix, child_ix, ());
        (edge_ix, child_ix)
    }

    /// Add an existing node (detached in the graph) to the tree.
    /// Note that floating nodes shouldn't exist for too long.
    pub fn attach_child(&mut self, parent_ix: NodeIndex, child_ix: NodeIndex)
                     -> EdgeIndex {
        // Make sure the child doesn't have a parent
        if cfg!(debug_assertions) && self.has_parent(child_ix) {
            panic!("attach_child: child had a parent!")
        }

        let parent_type = self.graph.node_weight(parent_ix)
            .expect("attach_child: parent not found").get_type();
        let child_type = self.graph.node_weight(child_ix)
            .expect("attach_child: child not found").get_type();

        if !parent_type.can_have_child(child_type) {
            panic!("Attempted to give a {:?} a {:?} child!",
                   parent_type, child_type);
        }

        return self.graph.update_edge(parent_ix, child_ix, ())
    }

    /// Detaches a node from the tree (causing there to be two trees).
    /// This should only be done temporarily.
    pub fn detach(&mut self, node_ix: NodeIndex) {
        let mut result: Option<NodeIndex> = None;
        if let Some(edge) = if cfg!(debug_assertions) {
            let edges = self.graph
                .neighbors_directed(node_ix, EdgeDirection::Incoming);
            let result = edges.next();
            if edges.next().is_some() {
                panic!("detach: node had more than one parent!")
            }
        }
        else {
            self.graph.neighbors_directed(node_ix, EdgeDirection::Incoming)
                .next()
        } {
            self.graph.remove_edge(edge);
        }
    }

    /// Moves a node between two indices
    pub fn move_node(&mut self, node_ix: NodeIndex, new_parent: NodeIndex) {
        self.detach(node_ix);
        self.attach_child(new_parent, node_ix);
    }

    /// Whether a node has a parent
    #[allow(dead_code)]
    pub fn has_parent(&self, node_ix: NodeIndex) -> bool {
        let neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        match neighbors.iter().count() {
            0 => false,
            1 => true,
            _ => panic!("Node has more than one parent!")
        }
    }

    /// Gets the parent of a node, if the node exists
    pub fn parent_of(&self, node_ix: NodeIndex) -> Option<NodeIndex> {
        let neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        if cfg!(debug_assertions) {
            let result = neighbors.next();
            if neighbors.next().is_some() {
                panic!("parent_of: node has multiple parents!")
            }
            result
        }
        else {
            neighbors.next()
        }
    }

    /// Gets an iterator to the children of a node.
    ///
    /// Will return an empty iterator if the node has no children or
    /// if the node does not exist.
    pub fn children_of(&self, node_ix: NodeIndex) -> Iter<NodeIndex> {
        self.graph.neighbors_directed(node_ix, EdgeDirection::Outgoing)
    }

    /// Gets the container of the given node.
    pub fn get(&self, node_ix: NodeIndex) -> &Container {
        self.graph.node_weight(node_ix)
            .expect("get: node not found")
    }

    /// Gets a mutable reference to a given node
    pub fn get_mut(&mut self, node_ix: NodeIndex) -> &mut Container {
        self.graph.node_weight_mut(node_ix)
            .expect("get_mut: node not found")
    }

    /// Gets the ContainerType of the selected node
    pub fn node_type(&self, node_ix: NodeIndex) -> ContainerType {
        let node = self.graph.node_weight(node_ix)
            .expect("node_type: node not found");
        node.get_type()
    }

    /// Attempts to get an ancestor matching the matching type
    pub fn ancestor_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        let mut curr_ix = node_ix;
        while let Some(parent_ix) = self.parent_of(curr_ix) {
            curr_ix = parent_ix;
            let parent = self.graph.node_weight(parent_ix)
                .expect("ancestor_of_type: parent_of invalid");
            if parent.get_type() == container_type() {
                return Some(parent_ix)
            }
            curr_ix = parent_ix;
        }
        return None;
    }

    /// Attempts to get a descendant of the matching type
    pub fn descendant_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        // TODO if self == type?
        for child in self.children_of(curr_ix) {
            if let Some(desc) = self.descendant_of_type(child, container_type) {
                    return Some(desc)
            }
        }
        return None
    }

    /// Finds a node by the view handle.
    pub fn descendant_with_handle(&self, node: NodeIndex, handle: &WlcView)
                               -> Option<NodeIndex> {
        match self.get(node) {
            &Container::View { ref node_handle, .. } => {
                if node_handle == handle {
                    Some(node)
                }
                else {
                    None
                }
            },
            _ => {
                for child in self.children_of(node) {
                    if let Some(view) = self.descendant_with_handle(handle) {
                        return Some(view)
                    }
                }
                return None
            }
        }
    }

    /// Sets the node and its children's visibility
    pub fn set_family_visible(&mut self, node_ix: NodeIndex, visible: bool) {
        self.get_mut(node_ix).set_visibility(visible);
        for child in self.children_of(node_ix) {
            self.get_mut(child).set_visibility(visible);
        }
    }
}

use std::ops::Index;

impl Index<Idx=NodeIndex> for Tree {
    type Output = Container;
    #[inline]
    fn index(&self, index: Idx) -> &Self::Output {
        self.get(index)
    }
}

impl IndexMut<Idx=NodeIndex> for Tree {
    type Output = Container;
    #[inline]
    fn index(&mut self, index: Idx) -> &mut Self::Output {
        self.get_mut(index)
    }
}
<commit_msg>Add root_ix to graph_tree, build still in shambles<commit_after>//! A tree represented via a petgraph graph, used for way-cooler's
//! layout.

use petgraph::EdgeDirection;
use petgraph::graph::{Graph, EdgeDirection, Node, Neighbors, NodeIndex};

use layout::{Container, ContainerType};

/// Layout tree implemented with petgraph.
#[derive(Debug)]
pub struct Tree {
    graph: Graph<Container, ()>, // Directed graph
    root: NodeIndex
}

impl Tree {
    /// Creates a new layout tree with a root node.
    pub fn new() -> Tree {
        let mut graph = Graph::new();
        let root_ix = graph.add_node(Container::Root);
        Tree { graph: graph, root: root_it }
    }

    /// Gets the index of the tree's root node
    pub fn root_ix(&self) -> NodeIndex {
        self.root
    }

    /// Adds a new child to a node at the index, returning the edge index
    /// of their connection and the index of the new node.
    // TODO should this return a result like the old API?
    pub fn add_child(&mut self, parent_ix: NodeIndex, val: Container)
                     -> (EdgeIndex, NodeIndex) {
        let parent = self.graph.node_weight(parent_ix)
            .expect("add_child: parent not found");
        if !parent.get_type().can_have_child(val.get_type()) {
            panic!("Attempted to give a {:?} a {:?} child!",
                   parent.get_type(), child.get_type())
        }
        let child_ix = self.graph.add_node(val);
        let edge_ix = self.graph.update_edge(parent_ix, child_ix, ());
        (edge_ix, child_ix)
    }

    /// Add an existing node (detached in the graph) to the tree.
    /// Note that floating nodes shouldn't exist for too long.
    pub fn attach_child(&mut self, parent_ix: NodeIndex, child_ix: NodeIndex)
                     -> EdgeIndex {
        // Make sure the child doesn't have a parent
        if cfg!(debug_assertions) && self.has_parent(child_ix) {
            panic!("attach_child: child had a parent!")
        }

        let parent_type = self.graph.node_weight(parent_ix)
            .expect("attach_child: parent not found").get_type();
        let child_type = self.graph.node_weight(child_ix)
            .expect("attach_child: child not found").get_type();

        if !parent_type.can_have_child(child_type) {
            panic!("Attempted to give a {:?} a {:?} child!",
                   parent_type, child_type);
        }

        return self.graph.update_edge(parent_ix, child_ix, ())
    }

    /// Detaches a node from the tree (causing there to be two trees).
    /// This should only be done temporarily.
    pub fn detach(&mut self, node_ix: NodeIndex) {
        let mut result: Option<NodeIndex> = None;
        if let Some(edge) = if cfg!(debug_assertions) {
            let edges = self.graph
                .neighbors_directed(node_ix, EdgeDirection::Incoming);
            let result = edges.next();
            if edges.next().is_some() {
                panic!("detach: node had more than one parent!")
            }
        }
        else {
            self.graph.neighbors_directed(node_ix, EdgeDirection::Incoming)
                .next()
        } {
            self.graph.remove_edge(edge);
        }
    }

    /// Moves a node between two indices
    pub fn move_node(&mut self, node_ix: NodeIndex, new_parent: NodeIndex) {
        self.detach(node_ix);
        self.attach_child(new_parent, node_ix);
    }

    /// Whether a node has a parent
    #[allow(dead_code)]
    pub fn has_parent(&self, node_ix: NodeIndex) -> bool {
        let neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        match neighbors.iter().count() {
            0 => false,
            1 => true,
            _ => panic!("Node has more than one parent!")
        }
    }

    /// Gets the parent of a node, if the node exists
    pub fn parent_of(&self, node_ix: NodeIndex) -> Option<NodeIndex> {
        let neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        if cfg!(debug_assertions) {
            let result = neighbors.next();
            if neighbors.next().is_some() {
                panic!("parent_of: node has multiple parents!")
            }
            result
        }
        else {
            neighbors.next()
        }
    }

    /// Gets an iterator to the children of a node.
    ///
    /// Will return an empty iterator if the node has no children or
    /// if the node does not exist.
    pub fn children_of(&self, node_ix: NodeIndex) -> Iter<NodeIndex> {
        self.graph.neighbors_directed(node_ix, EdgeDirection::Outgoing)
    }

    /// Gets the container of the given node.
    pub fn get(&self, node_ix: NodeIndex) -> &Container {
        self.graph.node_weight(node_ix)
            .expect("get: node not found")
    }

    /// Gets a mutable reference to a given node
    pub fn get_mut(&mut self, node_ix: NodeIndex) -> &mut Container {
        self.graph.node_weight_mut(node_ix)
            .expect("get_mut: node not found")
    }

    /// Gets the ContainerType of the selected node
    pub fn node_type(&self, node_ix: NodeIndex) -> ContainerType {
        let node = self.graph.node_weight(node_ix)
            .expect("node_type: node not found");
        node.get_type()
    }

    /// Attempts to get an ancestor matching the matching type
    pub fn ancestor_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        let mut curr_ix = node_ix;
        while let Some(parent_ix) = self.parent_of(curr_ix) {
            curr_ix = parent_ix;
            let parent = self.graph.node_weight(parent_ix)
                .expect("ancestor_of_type: parent_of invalid");
            if parent.get_type() == container_type() {
                return Some(parent_ix)
            }
            curr_ix = parent_ix;
        }
        return None;
    }

    /// Attempts to get a descendant of the matching type
    pub fn descendant_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        // TODO if self == type?
        for child in self.children_of(curr_ix) {
            if let Some(desc) = self.descendant_of_type(child, container_type) {
                    return Some(desc)
            }
        }
        return None
    }

    /// Finds a node by the view handle.
    pub fn descendant_with_handle(&self, node: NodeIndex, handle: &WlcView)
                               -> Option<NodeIndex> {
        match self.get(node) {
            &Container::View { ref node_handle, .. } => {
                if node_handle == handle {
                    Some(node)
                }
                else {
                    None
                }
            },
            _ => {
                for child in self.children_of(node) {
                    if let Some(view) = self.descendant_with_handle(handle) {
                        return Some(view)
                    }
                }
                return None
            }
        }
    }

    /// Sets the node and its children's visibility
    pub fn set_family_visible(&mut self, node_ix: NodeIndex, visible: bool) {
        self.get_mut(node_ix).set_visibility(visible);
        for child in self.children_of(node_ix) {
            self.get_mut(child).set_visibility(visible);
        }
    }
}

use std::ops::Index;

impl Index<Idx=NodeIndex> for Tree {
    type Output = Container;
    #[inline]
    fn index(&self, index: Idx) -> &Self::Output {
        self.get(index)
    }
}

impl IndexMut<Idx=NodeIndex> for Tree {
    type Output = Container;
    #[inline]
    fn index(&mut self, index: Idx) -> &mut Self::Output {
        self.get_mut(index)
    }
}
<|endoftext|>


<commit_before>//! Selection sort algorithm.
//!
//! The `selection` module contains the simple sorting algorithm "Selection Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Selection_sort

/// Simple sort: selection sort.
///
/// # Details
///
/// Selection sort is one of the simplest sorting algorithm. It sorts a vector in place by
/// looping over all elements and swapping the smallest element of the rest of the vector.
///
/// # Scaling
///
/// Selection sort in scale as O(N^2) since for all elements to sort, the algorithm will compare it
/// with every (remaining) elements.
///
/// Insertion sort is still useful as it is quite simple.
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::simplesorts::selection::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut Vec<T>) {

    if !array.is_empty() {
        // Let's loop over the input array, skipping last value (important as we want to get a
        // slice of the following values).
        let n = array.len();
        for i in 0..n-1 {
            // Find index of the minimum value in the slice of values following the i^th element.
            let j = {
                let int_slice = &array[i+1..];
                // k now holds the index (of "array") of the minimum element of "int_slice", or the
                // value "i" of the current element of "array" (which should be the less than
                // all elements of "int_slice").
                // "k" is a tuple containing the smallest element of "int_slice" and its index.
                //     k.0: Index of "int_slice" of its smallest value.
                //     k.1: Smallest value of "int_slice".
                let k = int_slice.iter().enumerate().fold(
                    (0, int_slice.first().unwrap()), |acc, item| {
                        if acc.1 > item.1 { item } else { acc }
                });

                // Return from the block the smallest element between the one at index "i" of
                // the "array" and the smallest one from the "int_slice" array.
                // NOTE: Since "k" worked on the subarray "int_slice", it's first element is the
                //       i^th element of "array". If "k" is actually smaller than "array[i]", we
                //       need to adapt the index as stored in "k.0".
                if k.1 < &array[i] { i + k.0 + 1 } else { i }
            };

            array.swap(i, j);
        }
    }
}
<commit_msg>Use a slice instead of a Vec for selection sort.<commit_after>//! Selection sort algorithm.
//!
//! The `selection` module contains the simple sorting algorithm "Selection Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Selection_sort

/// Simple sort: selection sort.
///
/// # Details
///
/// Selection sort is one of the simplest sorting algorithm. It sorts a vector in place by
/// looping over all elements and swapping the smallest element of the rest of the vector.
///
/// # Scaling
///
/// Selection sort in scale as O(N^2) since for all elements to sort, the algorithm will compare it
/// with every (remaining) elements.
///
/// Insertion sort is still useful as it is quite simple.
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::simplesorts::selection::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut [T]) {

    if !array.is_empty() {
        // Let's loop over the input array, skipping last value (important as we want to get a
        // slice of the following values).
        let n = array.len();
        for i in 0..n-1 {
            // Find index of the minimum value in the slice of values following the i^th element.
            let j = {
                let int_slice = &array[i+1..];
                // k now holds the index (of "array") of the minimum element of "int_slice", or the
                // value "i" of the current element of "array" (which should be the less than
                // all elements of "int_slice").
                // "k" is a tuple containing the smallest element of "int_slice" and its index.
                //     k.0: Index of "int_slice" of its smallest value.
                //     k.1: Smallest value of "int_slice".
                let k = int_slice.iter().enumerate().fold(
                    (0, int_slice.first().unwrap()), |acc, item| {
                        if acc.1 > item.1 { item } else { acc }
                });

                // Return from the block the smallest element between the one at index "i" of
                // the "array" and the smallest one from the "int_slice" array.
                // NOTE: Since "k" worked on the subarray "int_slice", it's first element is the
                //       i^th element of "array". If "k" is actually smaller than "array[i]", we
                //       need to adapt the index as stored in "k.0".
                if k.1 < &array[i] { i + k.0 + 1 } else { i }
            };

            array.swap(i, j);
        }
    }
}
<|endoftext|>


<commit_before>use crate::ty::subst::{SubstsRef, GenericArgKind};
use crate::ty::{self, Ty, TypeFlags, InferConst};
use crate::mir::interpret::ConstValue;

#[derive(Debug)]
pub struct FlagComputation {
    pub flags: TypeFlags,

    // see `TyS::outer_exclusive_binder` for details
    pub outer_exclusive_binder: ty::DebruijnIndex,
}

impl FlagComputation {
    fn new() -> FlagComputation {
        FlagComputation {
            flags: TypeFlags::empty(),
            outer_exclusive_binder: ty::INNERMOST,
        }
    }

    #[allow(rustc::usage_of_ty_tykind)]
    pub fn for_kind(kind: &ty::TyKind<'_>) -> FlagComputation {
        let mut result = FlagComputation::new();
        result.add_kind(kind);
        result
    }

    pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
        let mut result = FlagComputation::new();
        result.add_const(c);
        result.flags
    }

    fn add_flags(&mut self, flags: TypeFlags) {
        self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
    }

    /// indicates that `self` refers to something at binding level `binder`
    fn add_binder(&mut self, binder: ty::DebruijnIndex) {
        let exclusive_binder = binder.shifted_in(1);
        self.add_exclusive_binder(exclusive_binder);
    }

    /// indicates that `self` refers to something *inside* binding
    /// level `binder` -- not bound by `binder`, but bound by the next
    /// binder internal to it
    fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) {
        self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder);
    }

    /// Adds the flags/depth from a set of types that appear within the current type, but within a
    /// region binder.
    fn add_bound_computation(&mut self, computation: &FlagComputation) {
        self.add_flags(computation.flags);

        // The types that contributed to `computation` occurred within
        // a region binder, so subtract one from the region depth
        // within when adding the depth to `self`.
        let outer_exclusive_binder = computation.outer_exclusive_binder;
        if outer_exclusive_binder > ty::INNERMOST {
            self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
        } // otherwise, this binder captures nothing
    }

    #[allow(rustc::usage_of_ty_tykind)]
    fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
        match kind {
            &ty::Bool |
            &ty::Char |
            &ty::Int(_) |
            &ty::Float(_) |
            &ty::Uint(_) |
            &ty::Never |
            &ty::Str |
            &ty::Foreign(..) => {
            }

            // You might think that we could just return Error for
            // any type containing Error as a component, and get
            // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
            // the exception of function types that return bot).
            // But doing so caused sporadic memory corruption, and
            // neither I (tjc) nor nmatsakis could figure out why,
            // so we're doing it this way.
            &ty::Error => {
                self.add_flags(TypeFlags::HAS_TY_ERR)
            }

            &ty::Param(_) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_flags(TypeFlags::HAS_PARAMS);
            }

            &ty::Generator(_, ref substs, _) => {
                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_substs(substs);
            }

            &ty::GeneratorWitness(ref ts) => {
                let mut computation = FlagComputation::new();
                computation.add_tys(&ts.skip_binder()[..]);
                self.add_bound_computation(&computation);
            }

            &ty::Closure(_, ref substs) => {
                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_substs(substs);
            }

            &ty::Bound(debruijn, _) => {
                self.add_binder(debruijn);
            }

            &ty::Placeholder(..) => {
                self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
            }

            &ty::Infer(infer) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
                self.add_flags(TypeFlags::HAS_TY_INFER);
                match infer {
                    ty::FreshTy(_) |
                    ty::FreshIntTy(_) |
                    ty::FreshFloatTy(_) => {
                    }

                    ty::TyVar(_) |
                    ty::IntVar(_) |
                    ty::FloatVar(_) => {
                        self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
                    }
                }
            }

            &ty::Adt(_, substs) => {
                self.add_substs(substs);
            }

            &ty::Projection(ref data) => {
                self.add_flags(TypeFlags::HAS_PROJECTION);
                self.add_projection_ty(data);
            }

            &ty::UnnormalizedProjection(ref data) => {
                self.add_flags(TypeFlags::HAS_PROJECTION);
                self.add_projection_ty(data);
            },

            &ty::Opaque(_, substs) => {
                self.add_flags(TypeFlags::HAS_PROJECTION);
                self.add_substs(substs);
            }

            &ty::Dynamic(ref obj, r) => {
                let mut computation = FlagComputation::new();
                for predicate in obj.skip_binder().iter() {
                    match *predicate {
                        ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
                        ty::ExistentialPredicate::Projection(p) => {
                            let mut proj_computation = FlagComputation::new();
                            proj_computation.add_existential_projection(&p);
                            self.add_bound_computation(&proj_computation);
                        }
                        ty::ExistentialPredicate::AutoTrait(_) => {}
                    }
                }
                self.add_bound_computation(&computation);
                self.add_region(r);
            }

            &ty::Array(tt, len) => {
                self.add_ty(tt);
                self.add_const(len);
            }

            &ty::Slice(tt) => {
                self.add_ty(tt)
            }

            &ty::RawPtr(ref m) => {
                self.add_ty(m.ty);
            }

            &ty::Ref(r, ty, _) => {
                self.add_region(r);
                self.add_ty(ty);
            }

            &ty::Tuple(ref substs) => {
                self.add_substs(substs);
            }

            &ty::FnDef(_, substs) => {
                self.add_substs(substs);
            }

            &ty::FnPtr(f) => {
                self.add_fn_sig(f);
            }
        }
    }

    fn add_ty(&mut self, ty: Ty<'_>) {
        self.add_flags(ty.flags);
        self.add_exclusive_binder(ty.outer_exclusive_binder);
    }

    fn add_tys(&mut self, tys: &[Ty<'_>]) {
        for &ty in tys {
            self.add_ty(ty);
        }
    }

    fn add_fn_sig(&mut self, fn_sig: ty::PolyFnSig<'_>) {
        let mut computation = FlagComputation::new();

        computation.add_tys(fn_sig.skip_binder().inputs());
        computation.add_ty(fn_sig.skip_binder().output());

        self.add_bound_computation(&computation);
    }

    fn add_region(&mut self, r: ty::Region<'_>) {
        self.add_flags(r.type_flags());
        if let ty::ReLateBound(debruijn, _) = *r {
            self.add_binder(debruijn);
        }
    }

    fn add_const(&mut self, c: &ty::Const<'_>) {
        self.add_ty(c.ty);
        match c.val {
            ConstValue::Unevaluated(_, substs) => {
                self.add_substs(substs);
                self.add_flags(TypeFlags::HAS_PROJECTION);
            },
            ConstValue::Infer(infer) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
                match infer {
                    InferConst::Fresh(_) => {}
                    InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
                    InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
                }
            }
            ConstValue::Param(_) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS);
            }
            ConstValue::Placeholder(_) => {
                self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER);
            }
            ConstValue::Scalar(_) => { }
            ConstValue::Slice { data: _, start: _, end: _ } => { }
            ConstValue::ByRef { alloc: _, offset: _ } => { }
        }
    }

    fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
        self.add_substs(projection.substs);
        self.add_ty(projection.ty);
    }

    fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy<'_>) {
        self.add_substs(projection_ty.substs);
    }

    fn add_substs(&mut self, substs: SubstsRef<'_>) {
        for kind in substs {
            match kind.unpack() {
                GenericArgKind::Type(ty) => self.add_ty(ty),
                GenericArgKind::Lifetime(lt) => self.add_region(lt),
                GenericArgKind::Const(ct) => self.add_const(ct),
            }
        }
    }
}
<commit_msg>Correct handling of type flags with `ConstValue::Placeholder`<commit_after>use crate::ty::subst::{SubstsRef, GenericArgKind};
use crate::ty::{self, Ty, TypeFlags, InferConst};
use crate::mir::interpret::ConstValue;

#[derive(Debug)]
pub struct FlagComputation {
    pub flags: TypeFlags,

    // see `TyS::outer_exclusive_binder` for details
    pub outer_exclusive_binder: ty::DebruijnIndex,
}

impl FlagComputation {
    fn new() -> FlagComputation {
        FlagComputation {
            flags: TypeFlags::empty(),
            outer_exclusive_binder: ty::INNERMOST,
        }
    }

    #[allow(rustc::usage_of_ty_tykind)]
    pub fn for_kind(kind: &ty::TyKind<'_>) -> FlagComputation {
        let mut result = FlagComputation::new();
        result.add_kind(kind);
        result
    }

    pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
        let mut result = FlagComputation::new();
        result.add_const(c);
        result.flags
    }

    fn add_flags(&mut self, flags: TypeFlags) {
        self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
    }

    /// indicates that `self` refers to something at binding level `binder`
    fn add_binder(&mut self, binder: ty::DebruijnIndex) {
        let exclusive_binder = binder.shifted_in(1);
        self.add_exclusive_binder(exclusive_binder);
    }

    /// indicates that `self` refers to something *inside* binding
    /// level `binder` -- not bound by `binder`, but bound by the next
    /// binder internal to it
    fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) {
        self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder);
    }

    /// Adds the flags/depth from a set of types that appear within the current type, but within a
    /// region binder.
    fn add_bound_computation(&mut self, computation: &FlagComputation) {
        self.add_flags(computation.flags);

        // The types that contributed to `computation` occurred within
        // a region binder, so subtract one from the region depth
        // within when adding the depth to `self`.
        let outer_exclusive_binder = computation.outer_exclusive_binder;
        if outer_exclusive_binder > ty::INNERMOST {
            self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
        } // otherwise, this binder captures nothing
    }

    #[allow(rustc::usage_of_ty_tykind)]
    fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
        match kind {
            &ty::Bool |
            &ty::Char |
            &ty::Int(_) |
            &ty::Float(_) |
            &ty::Uint(_) |
            &ty::Never |
            &ty::Str |
            &ty::Foreign(..) => {
            }

            // You might think that we could just return Error for
            // any type containing Error as a component, and get
            // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
            // the exception of function types that return bot).
            // But doing so caused sporadic memory corruption, and
            // neither I (tjc) nor nmatsakis could figure out why,
            // so we're doing it this way.
            &ty::Error => {
                self.add_flags(TypeFlags::HAS_TY_ERR)
            }

            &ty::Param(_) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_flags(TypeFlags::HAS_PARAMS);
            }

            &ty::Generator(_, ref substs, _) => {
                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_substs(substs);
            }

            &ty::GeneratorWitness(ref ts) => {
                let mut computation = FlagComputation::new();
                computation.add_tys(&ts.skip_binder()[..]);
                self.add_bound_computation(&computation);
            }

            &ty::Closure(_, ref substs) => {
                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_substs(substs);
            }

            &ty::Bound(debruijn, _) => {
                self.add_binder(debruijn);
            }

            &ty::Placeholder(..) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
            }

            &ty::Infer(infer) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
                self.add_flags(TypeFlags::HAS_TY_INFER);
                match infer {
                    ty::FreshTy(_) |
                    ty::FreshIntTy(_) |
                    ty::FreshFloatTy(_) => {}

                    ty::TyVar(_) |
                    ty::IntVar(_) |
                    ty::FloatVar(_) => {
                        self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
                    }
                }
            }

            &ty::Adt(_, substs) => {
                self.add_substs(substs);
            }

            &ty::Projection(ref data) => {
                self.add_flags(TypeFlags::HAS_PROJECTION);
                self.add_projection_ty(data);
            }

            &ty::UnnormalizedProjection(ref data) => {
                self.add_flags(TypeFlags::HAS_PROJECTION);
                self.add_projection_ty(data);
            },

            &ty::Opaque(_, substs) => {
                self.add_flags(TypeFlags::HAS_PROJECTION);
                self.add_substs(substs);
            }

            &ty::Dynamic(ref obj, r) => {
                let mut computation = FlagComputation::new();
                for predicate in obj.skip_binder().iter() {
                    match *predicate {
                        ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
                        ty::ExistentialPredicate::Projection(p) => {
                            let mut proj_computation = FlagComputation::new();
                            proj_computation.add_existential_projection(&p);
                            self.add_bound_computation(&proj_computation);
                        }
                        ty::ExistentialPredicate::AutoTrait(_) => {}
                    }
                }
                self.add_bound_computation(&computation);
                self.add_region(r);
            }

            &ty::Array(tt, len) => {
                self.add_ty(tt);
                self.add_const(len);
            }

            &ty::Slice(tt) => {
                self.add_ty(tt)
            }

            &ty::RawPtr(ref m) => {
                self.add_ty(m.ty);
            }

            &ty::Ref(r, ty, _) => {
                self.add_region(r);
                self.add_ty(ty);
            }

            &ty::Tuple(ref substs) => {
                self.add_substs(substs);
            }

            &ty::FnDef(_, substs) => {
                self.add_substs(substs);
            }

            &ty::FnPtr(f) => {
                self.add_fn_sig(f);
            }
        }
    }

    fn add_ty(&mut self, ty: Ty<'_>) {
        self.add_flags(ty.flags);
        self.add_exclusive_binder(ty.outer_exclusive_binder);
    }

    fn add_tys(&mut self, tys: &[Ty<'_>]) {
        for &ty in tys {
            self.add_ty(ty);
        }
    }

    fn add_fn_sig(&mut self, fn_sig: ty::PolyFnSig<'_>) {
        let mut computation = FlagComputation::new();

        computation.add_tys(fn_sig.skip_binder().inputs());
        computation.add_ty(fn_sig.skip_binder().output());

        self.add_bound_computation(&computation);
    }

    fn add_region(&mut self, r: ty::Region<'_>) {
        self.add_flags(r.type_flags());
        if let ty::ReLateBound(debruijn, _) = *r {
            self.add_binder(debruijn);
        }
    }

    fn add_const(&mut self, c: &ty::Const<'_>) {
        self.add_ty(c.ty);
        match c.val {
            ConstValue::Unevaluated(_, substs) => {
                self.add_substs(substs);
                self.add_flags(TypeFlags::HAS_PROJECTION);
            },
            ConstValue::Infer(infer) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
                match infer {
                    InferConst::Fresh(_) => {}
                    InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
                    InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
                }
            }
            ConstValue::Param(_) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_flags(TypeFlags::HAS_PARAMS);
            }
            ConstValue::Placeholder(_) => {
                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
                self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
            }
            ConstValue::Scalar(_) => {}
            ConstValue::Slice { .. } => {}
            ConstValue::ByRef { .. } => {}
        }
    }

    fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
        self.add_substs(projection.substs);
        self.add_ty(projection.ty);
    }

    fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy<'_>) {
        self.add_substs(projection_ty.substs);
    }

    fn add_substs(&mut self, substs: SubstsRef<'_>) {
        for kind in substs {
            match kind.unpack() {
                GenericArgKind::Type(ty) => self.add_ty(ty),
                GenericArgKind::Lifetime(lt) => self.add_region(lt),
                GenericArgKind::Const(ct) => self.add_const(ct),
            }
        }
    }
}
<|endoftext|>


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

//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[doc(include = "os/raw/char.md")]
#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                       target_arch = "arm",
                                       target_arch = "powerpc",
                                       target_arch = "powerpc64",
                                       target_arch = "s390x")),
          all(target_os = "android", any(target_arch = "aarch64",
                                         target_arch = "arm")),
          all(target_os = "l4re", target_arch = "x86_64"),
          all(target_os = "netbsd", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc")),
          all(target_os = "openbsd", target_arch = "aarch64"),
          all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
#[doc(include = "os/raw/char.md")]
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                           target_arch = "arm",
                                           target_arch = "powerpc",
                                           target_arch = "powerpc64",
                                           target_arch = "s390x")),
              all(target_os = "android", any(target_arch = "aarch64",
                                             target_arch = "arm")),
              all(target_os = "l4re", target_arch = "x86_64"),
              all(target_os = "netbsd", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc")),
              all(target_os = "openbsd", target_arch = "aarch64"),
              all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
#[doc(include = "os/raw/schar.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
#[doc(include = "os/raw/uchar.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
#[doc(include = "os/raw/short.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
#[doc(include = "os/raw/ushort.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
#[doc(include = "os/raw/int.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
#[doc(include = "os/raw/uint.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
#[doc(include = "os/raw/long.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
#[doc(include = "os/raw/ulong.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
#[doc(include = "os/raw/long.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
#[doc(include = "os/raw/ulong.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
#[doc(include = "os/raw/longlong.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
#[doc(include = "os/raw/ulonglong.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
#[doc(include = "os/raw/float.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
#[doc(include = "os/raw/double.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

#[cfg(test)]
#[allow(unused_imports)]
mod tests {
    use any::TypeId;
    use libc;
    use mem;

    macro_rules! ok {
        ($($t:ident)*) => {$(
            assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
                    "{} is wrong", stringify!($t));
        )*}
    }

    #[test]
    fn same() {
        use os::raw;
        ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
            c_longlong c_ulonglong c_float c_double);
    }
}
<commit_msg>Add FreeBSD unsigned char platforms to std::os::raw<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[doc(include = "os/raw/char.md")]
#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                       target_arch = "arm",
                                       target_arch = "powerpc",
                                       target_arch = "powerpc64",
                                       target_arch = "s390x")),
          all(target_os = "android", any(target_arch = "aarch64",
                                         target_arch = "arm")),
          all(target_os = "l4re", target_arch = "x86_64"),
          all(target_os = "freebsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc",
                                         target_arch = "powerpc64")),
          all(target_os = "netbsd", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc")),
          all(target_os = "openbsd", target_arch = "aarch64"),
          all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
#[doc(include = "os/raw/char.md")]
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                           target_arch = "arm",
                                           target_arch = "powerpc",
                                           target_arch = "powerpc64",
                                           target_arch = "s390x")),
              all(target_os = "android", any(target_arch = "aarch64",
                                             target_arch = "arm")),
              all(target_os = "l4re", target_arch = "x86_64"),
              all(target_os = "freebsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc",
                                             target_arch = "powerpc64")),
              all(target_os = "netbsd", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc")),
              all(target_os = "openbsd", target_arch = "aarch64"),
              all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
#[doc(include = "os/raw/schar.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
#[doc(include = "os/raw/uchar.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
#[doc(include = "os/raw/short.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
#[doc(include = "os/raw/ushort.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
#[doc(include = "os/raw/int.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
#[doc(include = "os/raw/uint.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
#[doc(include = "os/raw/long.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
#[doc(include = "os/raw/ulong.md")]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
#[doc(include = "os/raw/long.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
#[doc(include = "os/raw/ulong.md")]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
#[doc(include = "os/raw/longlong.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
#[doc(include = "os/raw/ulonglong.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
#[doc(include = "os/raw/float.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
#[doc(include = "os/raw/double.md")]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

#[cfg(test)]
#[allow(unused_imports)]
mod tests {
    use any::TypeId;
    use libc;
    use mem;

    macro_rules! ok {
        ($($t:ident)*) => {$(
            assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
                    "{} is wrong", stringify!($t));
        )*}
    }

    #[test]
    fn same() {
        use os::raw;
        ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
            c_longlong c_ulonglong c_float c_double);
    }
}
<|endoftext|>


<commit_before>use nalgebra::Vector3;
use std::cmp::PartialEq;
use num::num_traits::Num;
use num::Zero;

/// Represents result of a steering behaviour computation. User can aggregate
/// more than one behaviour result into single acceleration struct.
pub struct SteeringAcceleration<T: Num>{
    pub linear : Vector3<T>,
    pub angular : T,
}

impl<T: Num> SteeringAcceleration<T>{
    fn new(linear_acceleration : Vector3<T>, angular_acceleration : T) -> SteeringAcceleration<T>{
        SteeringAcceleration{
            linear : linear_acceleration,
            angular : angular_acceleration,
        }
    }

    fn is_zero(self : &Self) -> bool{
        self.angular.is_zero()  && self.linear.is_zero()
    }
}
<commit_msg>new methods added to steering acceleration<commit_after>use nalgebra::{Vector3, Repeat};
use num::num_traits::Num;
use num::Zero;
use std::ops::AddAssign;
use std::ops::MulAssign;

/// Represents result of a steering behaviour computation. User can aggregate
/// more than one behaviour result into single acceleration struct.
pub struct SteeringAcceleration<T: Num + AddAssign + MulAssign + Copy> {
    pub linear: Vector3<T>,
    pub angular: T,
}

impl<T: Num + AddAssign + MulAssign + Copy> SteeringAcceleration<T> {
    /// Creates a steering acceleration struct using given linear and angular components
    fn new(linear_acceleration: Vector3<T>, angular_acceleration: T) -> SteeringAcceleration<T> {
        SteeringAcceleration {
            linear: linear_acceleration,
            angular: angular_acceleration,
        }
    }

    /// Tests whether both linear and angular acceleration compenents are zero
    fn is_zero(self: &Self) -> bool {
        self.angular.is_zero() && self.linear.is_zero()
    }

    /// Sets both compononents to zero
    fn set_zero(self: &mut Self) {
        self.angular = T::zero();
        self.linear = Vector3::zero();
    }

    ///
    fn add(self: &mut Self, other: SteeringAcceleration<T>) -> &mut Self {
        self.angular = self.angular + other.angular;
        self.linear += other.linear;
        self
    }

    fn scl(self : &mut Self, scale : T) -> &mut Self{
        self.angular = self.angular * scale;
        self.linear *= Vector3::repeat(scale);
        self
    }
}
<|endoftext|>


<commit_before>use nom::{ConsumerState, FileProducer, Needed, Move, Producer};
use std::io::{Error, ErrorKind, Result};
use std::u32;

use metadata::{
  Metadata, Data,
  StreamInfo, CueSheet, VorbisComment, Picture,
  PictureType,
};
use metadata::types::MetaDataConsumer;

// Will return true when the unwrapped value of `option` and `other` match
// or `option` is `Option::None`, otherwise false.
#[inline]
pub fn optional_eq<T: Eq>(option: Option<T>, other: T) -> bool {
  option.map_or(true, |value| value == other)
}

// With the given filename, return all metadata blocks available.
//
// This function expects a flac file, but will return a proper `Result::Err`
// when things go wrong.
//
// # Failures
//
// * `ErrorKind::NotFound` is returned when the given filename isn't found.
// * `ErrorKind::InvalidData` is returned when the data within the file
//   isn't valid FLAC data.
pub fn get_metadata(filename: &str) -> Result<Vec<Metadata>> {
  // TODO: There is a bug where the produced hangs when the buffer is to
  // small for the awaited ampunt of data. Will change back to 1024 as soon
  // as it is fixed.
  FileProducer::new(filename, 1024).and_then(|mut producer| {
    let mut consumer    = MetaDataConsumer::new();
    let mut buffer_size = 1024;
    let mut is_error    = false;

    loop {
      match *producer.apply(&mut consumer) {
        ConsumerState::Done(_, _)      => break,
        ConsumerState::Continue(await) => {
          if let Move::Await(needed) = await {
            if let Needed::Size(size) = needed {
              if size > buffer_size {
                producer.resize(size);
                buffer_size = size;
              }
            }
          }

          continue;
        }
        ConsumerState::Error(_)        => {
          is_error = true;

          break;
        }
      }
    }

    if is_error {
      let error_str = "parser: couldn't find any metadata";

      Err(Error::new(ErrorKind::InvalidData, error_str))
    } else {
      Ok(consumer.data)
    }
  })
}

/// Reads and returns the `StreamInfo` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `StreamInfo` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_stream_info("path/to/file.flac") {
///   Ok(stream_info) => {
///     // Use the stream_info variable...
///   }
///   Err(error)      => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let stream_info = metadata::get_stream_info("path/to/file.flac").unwrap();
/// ```
pub fn get_stream_info(filename: &str) -> Result<StreamInfo> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find StreamInfo";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    for block in blocks {
      if let Data::StreamInfo(stream_info) = block.data {
        result = Ok(stream_info);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `VorbisComment` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `VorbisComment` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_vorbis_comment("path/to/file.flac") {
///   Ok(vorbis_comment) => {
///     // Use the vorbis_comment variable...
///   }
///   Err(error)         => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let vorbis_comment =
///   metadata::get_vorbis_comment("path/to/file.flac").unwrap();
/// ```
pub fn get_vorbis_comment(filename: &str) -> Result<VorbisComment> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find VorbisComment";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    for block in blocks {
      if let Data::VorbisComment(vorbis_comment) = block.data {
        result = Ok(vorbis_comment);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `CueSheet` metadata block of the given FLAC file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `CueSheet` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_cue_sheet("path/to/file.flac") {
///   Ok(cue_sheet) => {
///     // Use the cue_sheet variable...
///   }
///   Err(error)    => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors
///
/// ```no_run
/// use flac::metadata;
///
/// let cue_sheet = metadata::get_cue_sheet("path/to/file.flac").unwrap();
/// ```
pub fn get_cue_sheet(filename: &str) -> Result<CueSheet> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find CueSheet";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    for block in blocks {
      if let Data::CueSheet(cue_sheet) = block.data {
        result = Ok(cue_sheet);
        break;
      }
    }

    result
  })
}

/// Reads and returns a `Picture` metadata block of the given FLAC file.
///
/// There can be more than one `Picture` block in a file and this function
/// takes optional, that being `Option<T>`, parameters that act as
/// constraints to search within. The `Picture` with the largest area
/// matching all constraints will be returned.
///
/// Putting `None` into any of the optional constraints conveys that you
/// want any of that parameter. Otherwise it will try to look for the image
/// that matches within the given constraints.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found,
///   there is no `Picture` within the file, or no `Picture` that fits the
///   given constraints.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let result = metadata::get_picture("path/to/file.flac",
///                                    Some(PictureType::FileIcon),
///                                    Some("image/gif"),
///                                    None, None, None,
///                                    None, None);
///
/// match result {
///   Ok(picture) => {
///     // Use the picture variable...
///   }
///   Err(error)  => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let picture = metadata::get_picture("path/to/file.flac",
///                                     Some(PictureType::FileIcon),
///                                     Some("image/gif"),
///                                     None, None, None,
///                                     None, None).unwrap();
/// ```
pub fn get_picture(filename: &str,
                   picture_type: Option<PictureType>,
                   mime_type: Option<&str>,
                   description: Option<&str>,
                   max_width: Option<u32>,
                   max_height: Option<u32>,
                   max_depth: Option<u32>,
                   max_colors: Option<u32>)
                   -> Result<Picture> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find any Picture";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    let mut max_area_seen  = 0;
    let mut max_depth_seen = 0;

    let max_value      = u32::max_value();
    let max_width_num  = max_width.unwrap_or(max_value);
    let max_height_num = max_height.unwrap_or(max_value);
    let max_depth_num  = max_depth.unwrap_or(max_value);
    let max_colors_num = max_colors.unwrap_or(max_value);

    for block in blocks {
      if let Data::Picture(picture) = block.data {
        let area = (picture.width as u64) * (picture.height as u64);

        if optional_eq(picture_type, picture.picture_type) &&
           optional_eq(mime_type, &picture.mime_type) &&
           optional_eq(description, &picture.description) &&
           picture.width <= max_width_num &&
           picture.height <= max_height_num &&
           picture.depth <= max_depth_num &&
           picture.colors <= max_colors_num &&
           (area > max_area_seen || (area == max_area_seen &&
                                     picture.depth > max_depth_seen)) {
          max_area_seen  = area;
          max_depth_seen = picture.depth;
          result         = Ok(picture);
        }
      }
    }

    result
  })
}

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

  #[test]
  #[should_panic]
  fn test_panic_optional_eq() {
    assert!(optional_eq(Some(1), 0));
  }

  #[test]
  fn test_optional_eq() {
    assert!(optional_eq(None, 0), "Should always return true when None");
    assert!(optional_eq(Some(0), 0), "Should return true (Some(0) == 0)");
  }

  #[test]
  fn test_get_metadata() {
    let not_found    = get_metadata("non-existent/file.txt");
    let invalid_data = get_metadata("README.md");
    let result       = get_metadata("tests/assets/input-SVAUP.flac");

    assert_eq!(not_found.unwrap_err().kind(), ErrorKind::NotFound);
    assert_eq!(invalid_data.unwrap_err().kind(), ErrorKind::InvalidData);
    assert!(result.is_ok());
  }
}
<commit_msg>Remove TODO note about the bug in nom<commit_after>use nom::{ConsumerState, FileProducer, Needed, Move, Producer};
use std::io::{Error, ErrorKind, Result};
use std::u32;

use metadata::{
  Metadata, Data,
  StreamInfo, CueSheet, VorbisComment, Picture,
  PictureType,
};
use metadata::types::MetaDataConsumer;

// Will return true when the unwrapped value of `option` and `other` match
// or `option` is `Option::None`, otherwise false.
#[inline]
pub fn optional_eq<T: Eq>(option: Option<T>, other: T) -> bool {
  option.map_or(true, |value| value == other)
}

// With the given filename, return all metadata blocks available.
//
// This function expects a flac file, but will return a proper `Result::Err`
// when things go wrong.
//
// # Failures
//
// * `ErrorKind::NotFound` is returned when the given filename isn't found.
// * `ErrorKind::InvalidData` is returned when the data within the file
//   isn't valid FLAC data.
pub fn get_metadata(filename: &str) -> Result<Vec<Metadata>> {
  FileProducer::new(filename, 1024).and_then(|mut producer| {
    let mut consumer    = MetaDataConsumer::new();
    let mut buffer_size = 1024;
    let mut is_error    = false;

    loop {
      match *producer.apply(&mut consumer) {
        ConsumerState::Done(_, _)      => break,
        ConsumerState::Continue(await) => {
          if let Move::Await(needed) = await {
            if let Needed::Size(size) = needed {
              if size > buffer_size {
                producer.resize(size);
                buffer_size = size;
              }
            }
          }

          continue;
        }
        ConsumerState::Error(_)        => {
          is_error = true;

          break;
        }
      }
    }

    if is_error {
      let error_str = "parser: couldn't find any metadata";

      Err(Error::new(ErrorKind::InvalidData, error_str))
    } else {
      Ok(consumer.data)
    }
  })
}

/// Reads and returns the `StreamInfo` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `StreamInfo` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_stream_info("path/to/file.flac") {
///   Ok(stream_info) => {
///     // Use the stream_info variable...
///   }
///   Err(error)      => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let stream_info = metadata::get_stream_info("path/to/file.flac").unwrap();
/// ```
pub fn get_stream_info(filename: &str) -> Result<StreamInfo> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find StreamInfo";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    for block in blocks {
      if let Data::StreamInfo(stream_info) = block.data {
        result = Ok(stream_info);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `VorbisComment` metadata block of the given FLAC
/// file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `VorbisComment` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_vorbis_comment("path/to/file.flac") {
///   Ok(vorbis_comment) => {
///     // Use the vorbis_comment variable...
///   }
///   Err(error)         => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
///
/// let vorbis_comment =
///   metadata::get_vorbis_comment("path/to/file.flac").unwrap();
/// ```
pub fn get_vorbis_comment(filename: &str) -> Result<VorbisComment> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find VorbisComment";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    for block in blocks {
      if let Data::VorbisComment(vorbis_comment) = block.data {
        result = Ok(vorbis_comment);
        break;
      }
    }

    result
  })
}

/// Reads and returns the `CueSheet` metadata block of the given FLAC file.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found
///   or there is no `CueSheet` within the file.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
///
/// match metadata::get_cue_sheet("path/to/file.flac") {
///   Ok(cue_sheet) => {
///     // Use the cue_sheet variable...
///   }
///   Err(error)    => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors
///
/// ```no_run
/// use flac::metadata;
///
/// let cue_sheet = metadata::get_cue_sheet("path/to/file.flac").unwrap();
/// ```
pub fn get_cue_sheet(filename: &str) -> Result<CueSheet> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find CueSheet";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    for block in blocks {
      if let Data::CueSheet(cue_sheet) = block.data {
        result = Ok(cue_sheet);
        break;
      }
    }

    result
  })
}

/// Reads and returns a `Picture` metadata block of the given FLAC file.
///
/// There can be more than one `Picture` block in a file and this function
/// takes optional, that being `Option<T>`, parameters that act as
/// constraints to search within. The `Picture` with the largest area
/// matching all constraints will be returned.
///
/// Putting `None` into any of the optional constraints conveys that you
/// want any of that parameter. Otherwise it will try to look for the image
/// that matches within the given constraints.
///
/// # Failures
///
/// * `ErrorKind::NotFound` is returned when the given filename isn't found,
///   there is no `Picture` within the file, or no `Picture` that fits the
///   given constraints.
/// * `ErrorKind::InvalidData` is returned when the data within the file
///   isn't valid FLAC data.
///
/// # Examples
///
/// Handling errors might look something like this:
///
/// ```
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let result = metadata::get_picture("path/to/file.flac",
///                                    Some(PictureType::FileIcon),
///                                    Some("image/gif"),
///                                    None, None, None,
///                                    None, None);
///
/// match result {
///   Ok(picture) => {
///     // Use the picture variable...
///   }
///   Err(error)  => println!("{}", error),
/// }
/// ```
///
/// Or just ignore the errors:
///
/// ```no_run
/// use flac::metadata;
/// use flac::metadata::PictureType;
///
/// let picture = metadata::get_picture("path/to/file.flac",
///                                     Some(PictureType::FileIcon),
///                                     Some("image/gif"),
///                                     None, None, None,
///                                     None, None).unwrap();
/// ```
pub fn get_picture(filename: &str,
                   picture_type: Option<PictureType>,
                   mime_type: Option<&str>,
                   description: Option<&str>,
                   max_width: Option<u32>,
                   max_height: Option<u32>,
                   max_depth: Option<u32>,
                   max_colors: Option<u32>)
                   -> Result<Picture> {
  get_metadata(filename).and_then(|blocks| {
    let error_str  = "metadata: couldn't find any Picture";
    let mut result = Err(Error::new(ErrorKind::NotFound, error_str));

    let mut max_area_seen  = 0;
    let mut max_depth_seen = 0;

    let max_value      = u32::max_value();
    let max_width_num  = max_width.unwrap_or(max_value);
    let max_height_num = max_height.unwrap_or(max_value);
    let max_depth_num  = max_depth.unwrap_or(max_value);
    let max_colors_num = max_colors.unwrap_or(max_value);

    for block in blocks {
      if let Data::Picture(picture) = block.data {
        let area = (picture.width as u64) * (picture.height as u64);

        if optional_eq(picture_type, picture.picture_type) &&
           optional_eq(mime_type, &picture.mime_type) &&
           optional_eq(description, &picture.description) &&
           picture.width <= max_width_num &&
           picture.height <= max_height_num &&
           picture.depth <= max_depth_num &&
           picture.colors <= max_colors_num &&
           (area > max_area_seen || (area == max_area_seen &&
                                     picture.depth > max_depth_seen)) {
          max_area_seen  = area;
          max_depth_seen = picture.depth;
          result         = Ok(picture);
        }
      }
    }

    result
  })
}

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

  #[test]
  #[should_panic]
  fn test_panic_optional_eq() {
    assert!(optional_eq(Some(1), 0));
  }

  #[test]
  fn test_optional_eq() {
    assert!(optional_eq(None, 0), "Should always return true when None");
    assert!(optional_eq(Some(0), 0), "Should return true (Some(0) == 0)");
  }

  #[test]
  fn test_get_metadata() {
    let not_found    = get_metadata("non-existent/file.txt");
    let invalid_data = get_metadata("README.md");
    let result       = get_metadata("tests/assets/input-SVAUP.flac");

    assert_eq!(not_found.unwrap_err().kind(), ErrorKind::NotFound);
    assert_eq!(invalid_data.unwrap_err().kind(), ErrorKind::InvalidData);
    assert!(result.is_ok());
  }
}
<|endoftext|>