<commit_before>use std::fmt;
use std::io::prelude::*;
use std::io;

use term::color::{Color, BLACK, RED, GREEN, YELLOW};
use term::{self, Terminal, TerminfoTerminal, color, Attr};

use self::AdequateTerminal::{NoColor, Colored};
use self::Verbosity::{Verbose, Normal, Quiet};
use self::ColorConfig::{Auto, Always, Never};

use util::errors::CargoResult;

#[derive(Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet
}

#[derive(Clone, Copy, PartialEq)]
pub enum ColorConfig {
    Auto,
    Always,
    Never
}

#[derive(Clone, Copy)]
pub struct ShellConfig {
    pub color_config: ColorConfig,
    pub tty: bool
}

enum AdequateTerminal {
    NoColor(Box<Write + Send>),
    Colored(Box<Terminal<Output=Box<Write + Send>> + Send>)
}

pub struct Shell {
    terminal: AdequateTerminal,
    config: ShellConfig,
}

pub struct MultiShell {
    out: Shell,
    err: Shell,
    verbosity: Verbosity
}

impl MultiShell {
    pub fn new(out: Shell, err: Shell, verbosity: Verbosity) -> MultiShell {
        MultiShell { out: out, err: err, verbosity: verbosity }
    }

    pub fn out(&mut self) -> &mut Shell {
        &mut self.out
    }

    pub fn err(&mut self) -> &mut Shell {
        &mut self.err
    }

    pub fn say<T: ToString>(&mut self, message: T, color: Color)
                            -> CargoResult<()> {
        match self.verbosity {
            Quiet => Ok(()),
            _ => self.out().say(message, color)
        }
    }

    pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
        where T: fmt::Display, U: fmt::Display
    {
        match self.verbosity {
            Quiet => Ok(()),
            _ => self.out().say_status(status, message, GREEN)
        }
    }

    pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
        where F: FnMut(&mut MultiShell) -> CargoResult<()>
    {
        match self.verbosity {
            Verbose => callback(self),
            _ => Ok(())
        }
    }

    pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
        where F: FnMut(&mut MultiShell) -> CargoResult<()>
    {
        match self.verbosity {
            Verbose => Ok(()),
            _ => callback(self)
        }
    }

    pub fn error<T: ToString>(&mut self, message: T) -> CargoResult<()> {
        self.err().say(message, RED)
    }

    pub fn warn<T: ToString>(&mut self, message: T) -> CargoResult<()> {
        self.err().say(message, YELLOW)
    }

    pub fn set_verbosity(&mut self, verbose: bool, quiet: bool) -> CargoResult<()> {
        self.verbosity = match (verbose, quiet) {
            (true, true) => bail!("cannot set both --verbose and --quiet"),
            (true, false) => Verbose,
            (false, true) => Quiet,
            (false, false) => Normal
        };
        Ok(())
    }

    /// shortcut for commands that don't have both --verbose and --quiet
    pub fn set_verbose(&mut self, verbose: bool) {
        if verbose {
            self.verbosity = Verbose;
        } else {
            self.verbosity = Normal;
        }
    }

    pub fn set_color_config(&mut self, color: Option<&str>) -> CargoResult<()> {
        self.out.set_color_config(match color {
            Some("auto") => Auto,
            Some("always") => Always,
            Some("never") => Never,

            None => Auto,

            Some(arg) => bail!("argument for --color must be auto, always, or \
                                never, but found `{}`", arg),
        });
        Ok(())
    }

    pub fn get_verbose(&self) -> Verbosity {
        self.verbosity
    }
}

impl Shell {
    pub fn create(out: Box<Write + Send>, config: ShellConfig) -> Shell {
        // Match from_env() to determine if creation of a TerminfoTerminal is possible regardless
        // of the tty status. --color options are parsed after Shell creation so always try to
        // create a terminal that supports color output. Fall back to a no-color terminal or write
        // output to stderr if a tty is present and color output is not possible.
        match ::term::terminfo::TermInfo::from_env() {
            Ok(ti) => {
                let term = TerminfoTerminal::new_with_terminfo(out, ti);
                // Color output is possible.
                if !term.supports_color() {
                    Err(term.into_inner())
                } else {
                    Ok(Shell {
                        terminal: Colored(Box::new(term)),
                        config: config
                    })
                }
            }
            Err(_) => Err(out)
        }.unwrap_or_else(|out| Shell {
            // If config.tty is set, we should be able to color output but can't. Write to stderr.
            terminal: NoColor(if config.tty { Box::new(io::stderr()) } else { out }),
            config: config,
        })
    }

    pub fn set_color_config(&mut self, color_config: ColorConfig) {
        self.config.color_config = color_config;
    }

    pub fn say<T: ToString>(&mut self, message: T, color: Color) -> CargoResult<()> {
        try!(self.reset());
        if color != BLACK { try!(self.fg(color)); }
        try!(write!(self, "{}\n", message.to_string()));
        try!(self.reset());
        try!(self.flush());
        Ok(())
    }

    pub fn say_status<T, U>(&mut self, status: T, message: U, color: Color)
                            -> CargoResult<()>
        where T: fmt::Display, U: fmt::Display
    {
        try!(self.reset());
        if color != BLACK { try!(self.fg(color)); }
        if self.supports_attr(Attr::Bold) { try!(self.attr(Attr::Bold)); }
        try!(write!(self, "{:>12}", status.to_string()));
        try!(self.reset());
        try!(write!(self, " {}\n", message));
        try!(self.flush());
        Ok(())
    }

    fn fg(&mut self, color: color::Color) -> CargoResult<bool> {
        let colored = self.colored();

        match self.terminal {
            Colored(ref mut c) if colored => try!(c.fg(color)),
            _ => return Ok(false),
        }
        Ok(true)
    }

    fn attr(&mut self, attr: Attr) -> CargoResult<bool> {
        let colored = self.colored();

        match self.terminal {
            Colored(ref mut c) if colored => try!(c.attr(attr)),
            _ => return Ok(false)
        }
        Ok(true)
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        let colored = self.colored();

        match self.terminal {
            Colored(ref c) if colored => c.supports_attr(attr),
            _ => false
        }
    }

    fn reset(&mut self) -> term::Result<()> {
        let colored = self.colored();

        match self.terminal {
            Colored(ref mut c) if colored => try!(c.reset()),
            _ => ()
        }
        Ok(())
    }

    fn colored(&self) -> bool {
        self.config.tty && Auto == self.config.color_config
            || Always == self.config.color_config
    }
}

impl Write for Shell {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self.terminal {
            Colored(ref mut c) => c.write(buf),
            NoColor(ref mut n) => n.write(buf)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self.terminal {
            Colored(ref mut c) => c.flush(),
            NoColor(ref mut n) => n.flush()
        }
    }
}
<commit_msg>Don't fall back on stderr if color is unavailable<commit_after>use std::fmt;
use std::io::prelude::*;
use std::io;

use term::color::{Color, BLACK, RED, GREEN, YELLOW};
use term::{self, Terminal, TerminfoTerminal, color, Attr};

use self::AdequateTerminal::{NoColor, Colored};
use self::Verbosity::{Verbose, Normal, Quiet};
use self::ColorConfig::{Auto, Always, Never};

use util::errors::CargoResult;

#[derive(Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet
}

#[derive(Clone, Copy, PartialEq)]
pub enum ColorConfig {
    Auto,
    Always,
    Never
}

#[derive(Clone, Copy)]
pub struct ShellConfig {
    pub color_config: ColorConfig,
    pub tty: bool
}

enum AdequateTerminal {
    NoColor(Box<Write + Send>),
    Colored(Box<Terminal<Output=Box<Write + Send>> + Send>)
}

pub struct Shell {
    terminal: AdequateTerminal,
    config: ShellConfig,
}

pub struct MultiShell {
    out: Shell,
    err: Shell,
    verbosity: Verbosity
}

impl MultiShell {
    pub fn new(out: Shell, err: Shell, verbosity: Verbosity) -> MultiShell {
        MultiShell { out: out, err: err, verbosity: verbosity }
    }

    pub fn out(&mut self) -> &mut Shell {
        &mut self.out
    }

    pub fn err(&mut self) -> &mut Shell {
        &mut self.err
    }

    pub fn say<T: ToString>(&mut self, message: T, color: Color)
                            -> CargoResult<()> {
        match self.verbosity {
            Quiet => Ok(()),
            _ => self.out().say(message, color)
        }
    }

    pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
        where T: fmt::Display, U: fmt::Display
    {
        match self.verbosity {
            Quiet => Ok(()),
            _ => self.out().say_status(status, message, GREEN)
        }
    }

    pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
        where F: FnMut(&mut MultiShell) -> CargoResult<()>
    {
        match self.verbosity {
            Verbose => callback(self),
            _ => Ok(())
        }
    }

    pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
        where F: FnMut(&mut MultiShell) -> CargoResult<()>
    {
        match self.verbosity {
            Verbose => Ok(()),
            _ => callback(self)
        }
    }

    pub fn error<T: ToString>(&mut self, message: T) -> CargoResult<()> {
        self.err().say(message, RED)
    }

    pub fn warn<T: ToString>(&mut self, message: T) -> CargoResult<()> {
        self.err().say(message, YELLOW)
    }

    pub fn set_verbosity(&mut self, verbose: bool, quiet: bool) -> CargoResult<()> {
        self.verbosity = match (verbose, quiet) {
            (true, true) => bail!("cannot set both --verbose and --quiet"),
            (true, false) => Verbose,
            (false, true) => Quiet,
            (false, false) => Normal
        };
        Ok(())
    }

    /// shortcut for commands that don't have both --verbose and --quiet
    pub fn set_verbose(&mut self, verbose: bool) {
        if verbose {
            self.verbosity = Verbose;
        } else {
            self.verbosity = Normal;
        }
    }

    pub fn set_color_config(&mut self, color: Option<&str>) -> CargoResult<()> {
        self.out.set_color_config(match color {
            Some("auto") => Auto,
            Some("always") => Always,
            Some("never") => Never,

            None => Auto,

            Some(arg) => bail!("argument for --color must be auto, always, or \
                                never, but found `{}`", arg),
        });
        Ok(())
    }

    pub fn get_verbose(&self) -> Verbosity {
        self.verbosity
    }
}

impl Shell {
    pub fn create(out: Box<Write + Send>, config: ShellConfig) -> Shell {
        // Use `TermInfo::from_env()` and `TerminfoTerminal::supports_color()`
        // to determine if creation of a TerminfoTerminal is possible regardless
        // of the tty status. --color options are parsed after Shell creation so
        // always try to create a terminal that supports color output. Fall back
        // to a no-color terminal regardless of whether or not a tty is present
        // and if color output is not possible.
        Shell {
            terminal: match ::term::terminfo::TermInfo::from_env() {
                Ok(ti) => {
                    let term = TerminfoTerminal::new_with_terminfo(out, ti);
                    if !term.supports_color() {
                        NoColor(term.into_inner())
                    } else {
                        // Color output is possible.
                        Colored(Box::new(term))
                    }
                },
                Err(_) => NoColor(out),
            },
            config: config,
        }
    }

    pub fn set_color_config(&mut self, color_config: ColorConfig) {
        self.config.color_config = color_config;
    }

    pub fn say<T: ToString>(&mut self, message: T, color: Color) -> CargoResult<()> {
        try!(self.reset());
        if color != BLACK { try!(self.fg(color)); }
        try!(write!(self, "{}\n", message.to_string()));
        try!(self.reset());
        try!(self.flush());
        Ok(())
    }

    pub fn say_status<T, U>(&mut self, status: T, message: U, color: Color)
                            -> CargoResult<()>
        where T: fmt::Display, U: fmt::Display
    {
        try!(self.reset());
        if color != BLACK { try!(self.fg(color)); }
        if self.supports_attr(Attr::Bold) { try!(self.attr(Attr::Bold)); }
        try!(write!(self, "{:>12}", status.to_string()));
        try!(self.reset());
        try!(write!(self, " {}\n", message));
        try!(self.flush());
        Ok(())
    }

    fn fg(&mut self, color: color::Color) -> CargoResult<bool> {
        let colored = self.colored();

        match self.terminal {
            Colored(ref mut c) if colored => try!(c.fg(color)),
            _ => return Ok(false),
        }
        Ok(true)
    }

    fn attr(&mut self, attr: Attr) -> CargoResult<bool> {
        let colored = self.colored();

        match self.terminal {
            Colored(ref mut c) if colored => try!(c.attr(attr)),
            _ => return Ok(false)
        }
        Ok(true)
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        let colored = self.colored();

        match self.terminal {
            Colored(ref c) if colored => c.supports_attr(attr),
            _ => false
        }
    }

    fn reset(&mut self) -> term::Result<()> {
        let colored = self.colored();

        match self.terminal {
            Colored(ref mut c) if colored => try!(c.reset()),
            _ => ()
        }
        Ok(())
    }

    fn colored(&self) -> bool {
        self.config.tty && Auto == self.config.color_config
            || Always == self.config.color_config
    }
}

impl Write for Shell {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self.terminal {
            Colored(ref mut c) => c.write(buf),
            NoColor(ref mut n) => n.write(buf)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self.terminal {
            Colored(ref mut c) => c.flush(),
            NoColor(ref mut n) => n.flush()
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

pub type UnderlyingError = Box<Error + Send + Sync>;
#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(UnderlyingError),
    DeserializeError(UnderlyingError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => err.description(),
            TransitError::SerializeError(ref err) => err.description(),
            TransitError::DeserializeError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

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

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; 65535]; // Max size of UDP packet
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(65535);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

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

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<commit_msg>Use UDP packet size constant<commit_after>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

const MAX_UDP_SIZE: u16 = 65535;
pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

pub type UnderlyingError = Box<Error + Send + Sync>;
#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(UnderlyingError),
    DeserializeError(UnderlyingError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => err.description(),
            TransitError::SerializeError(ref err) => err.description(),
            TransitError::DeserializeError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

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

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; MAX_UDP_SIZE as usize];
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(MAX_UDP_SIZE as u64);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

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

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::io;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

/// The From trait in the standard library does not allow for errors to occur. This is useful
/// particularly when converting a type from a byte array received from the network that may or may
/// not be of the particular type.
pub trait FromTransit<T> {
    fn from_transit(T) -> io::Result<Self>;
}

/// Like the FromTransit trait, the IntoTransit trait modifies the idea of the into trait.
/// Specifically, the IntoTransit trait takes a reference to self and specifies a lifetime. This
/// allows an implementor to keep using the object while tying the lifetime of the return type T to
/// the implementor's lifetime.
pub trait IntoTransit<'a, T> {
    fn into_transit(&'a self) -> T;
}

impl<T: for<'a> FromTransit<&'a [u8]> + for<'a> IntoTransit<'a, &'a [u8]>> Transit<T> {
    pub fn new<A>(addr: A) -> io::Result<Transit<T>> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the FromTransit trait
    /// implementation. The trait implementation should be able to detect whether or not the buffer
    /// contains a valid UDP message and emit an error appropriately.
    pub fn recv_from(&self) -> io::Result<(T, SocketAddr)> {
        let mut buf = [0; 1024];
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        assert!(n <= 1024);
        let data = try!(T::from_transit(&buf));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: T, addr: A) -> io::Result<()> where A: ToSocketAddrs {
        let buf = pkt.into_transit();
        try!(self.socket.send_to(buf, addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> io::Result<SocketAddr> {
        self.socket.local_addr()
    }
}

#[cfg(test)]
mod test {
    use udp::*;
    use std::slice;
    use std::io::{self, Error, ErrorKind};

    #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    impl<'a> IntoTransit<'a, &'a [u8]> for Test {
        fn into_transit(&'a self) -> &'a [u8] {
            unsafe { slice::from_raw_parts(&self.ten as *const u8, 1) }
        }
    }

    impl<'a> FromTransit<&'a [u8]> for Test {
        fn from_transit(buf: &'a [u8]) -> io::Result<Test> {
            if buf[0] != 10 {
                Err(Error::new(ErrorKind::InvalidData, "failed to serialize"))
            } else {
                Ok(Test { ten: buf[0] })
            }
        }
    }

    #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: u8,
    }

    impl<'a> IntoTransit<'a, &'a [u8]> for Another {
        fn into_transit(&'a self) -> &'a [u8] {
            unsafe { slice::from_raw_parts(&self.data as *const u8, 1) }
        }
    }

    impl<'a> FromTransit<&'a [u8]> for Another {
        fn from_transit(buf: &'a [u8]) -> io::Result<Another> {
            Ok(Another { data: buf[0] })
        }
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_packet_type() {
        let addr1 = "127.0.0.1:62001";
        let addr2 = "127.0.0.1:62002";
        let transit1: Transit<Another> = Transit::new(addr1).unwrap();
        let transit2: Transit<Test> = Transit::new(addr2).unwrap();
        let test = Another { data: 27 };

        let res = transit1.send_to(test, addr2);
        assert!(res.is_ok());
        let res = transit2.recv_from();
        assert!(res.is_err());
    }
}
<commit_msg>Add implementation for String<commit_after>use std::marker::PhantomData;
use std::io::{self, ErrorKind};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

/// The From trait in the standard library does not allow for errors to occur. This is useful
/// particularly when converting a type from a byte array received from the network that may or may
/// not be of the particular type.
pub trait FromTransit<T> {
    fn from_transit(T) -> io::Result<Self> where Self: Sized;
}

impl<'a> FromTransit<&'a [u8]> for String {
    fn from_transit(buf: &'a [u8]) -> io::Result<String> {
        let vec = Vec::from(buf);
        let res = String::from_utf8(vec);
        match res {
            Err(utf8err) => Err(io::Error::new(ErrorKind::InvalidData, utf8err.description())),
            Ok(string) => Ok(string),
        }
    }
}

/// Like the FromTransit trait, the IntoTransit trait modifies the idea of the into trait.
/// Specifically, the IntoTransit trait takes a reference to self and specifies a lifetime. This
/// allows an implementor to keep using the object while tying the lifetime of the return type T to
/// the implementor's lifetime.
pub trait IntoTransit<'a, T> {
    fn into_transit(&'a self) -> T;
}

impl<'a> IntoTransit<'a, &'a [u8]> for String {
    fn into_transit(&'a self) -> &'a [u8] {
        self.as_bytes()
    }
}

impl<T: for<'a> FromTransit<&'a [u8]> + for<'a> IntoTransit<'a, &'a [u8]>> Transit<T> {
    pub fn new<A>(addr: A) -> io::Result<Transit<T>> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the FromTransit trait
    /// implementation. The trait implementation should be able to detect whether or not the buffer
    /// contains a valid UDP message and emit an error appropriately.
    pub fn recv_from(&self) -> io::Result<(T, SocketAddr)> {
        let mut buf = [0; 1024];
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        assert!(n < 1024);
        let data = try!(T::from_transit(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: T, addr: A) -> io::Result<()> where A: ToSocketAddrs {
        let buf = pkt.into_transit();
        try!(self.socket.send_to(buf, addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> io::Result<SocketAddr> {
        self.socket.local_addr()
    }
}

#[cfg(test)]
mod test {
    use udp::*;
    use std::slice;
    use std::io::{self, Error, ErrorKind};

    #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    impl<'a> IntoTransit<'a, &'a [u8]> for Test {
        fn into_transit(&'a self) -> &'a [u8] {
            unsafe { slice::from_raw_parts(&self.ten as *const u8, 1) }
        }
    }

    impl<'a> FromTransit<&'a [u8]> for Test {
        fn from_transit(buf: &'a [u8]) -> io::Result<Test> {
            if buf[0] != 10 {
                Err(Error::new(ErrorKind::InvalidData, "failed to serialize"))
            } else {
                Ok(Test { ten: buf[0] })
            }
        }
    }

    #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: u8,
    }

    impl<'a> IntoTransit<'a, &'a [u8]> for Another {
        fn into_transit(&'a self) -> &'a [u8] {
            unsafe { slice::from_raw_parts(&self.data as *const u8, 1) }
        }
    }

    impl<'a> FromTransit<&'a [u8]> for Another {
        fn from_transit(buf: &'a [u8]) -> io::Result<Another> {
            Ok(Another { data: buf[0] })
        }
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(test.clone(), addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_packet_type() {
        let addr1 = "127.0.0.1:62001";
        let addr2 = "127.0.0.1:62002";
        let transit1: Transit<Another> = Transit::new(addr1).unwrap();
        let transit2: Transit<Test> = Transit::new(addr2).unwrap();
        let test = Another { data: 27 };

        let res = transit1.send_to(test, addr2);
        assert!(res.is_ok());
        let res = transit2.recv_from();
        assert!(res.is_err());
    }
}
<|endoftext|>


<commit_before>// xfail-fast
#[legacy_modes];

use cmp::Eq;

fn iter<T>(v: ~[T], it: fn(T) -> bool) {
    let mut i = 0u, l = v.len();
    while i < l {
        if !it(v[i]) { break; }
        i += 1u;
    }
}

fn find_pos<T:Eq>(n: T, h: ~[T]) -> Option<uint> {
    let mut i = 0u;
    for iter(copy h) |e| {
        if e == n { return Some(i); }
        i += 1u;
    }
    None
}

fn bail_deep(x: ~[~[bool]]) {
    let mut seen = false;
    for iter(copy x) |x| {
        for iter(copy x) |x| {
            assert !seen;
            if x { seen = true; return; }
        }
    }
    assert !seen;
}

fn ret_deep() -> ~str {
    for iter(~[1, 2]) |e| {
        for iter(~[3, 4]) |x| {
            if e + x > 4 { return ~"hi"; }
        }
    }
    return ~"bye";
}

fn main() {
    let mut last = 0;
    for vec::all(~[1, 2, 3, 4, 5, 6, 7]) |e| {
        last = *e;
        if *e == 5 { break; }
        if *e % 2 == 1 { loop; }
        assert *e % 2 == 0;
    };
    assert last == 5;

    assert find_pos(1, ~[0, 1, 2, 3]) == Some(1u);
    assert find_pos(1, ~[0, 4, 2, 3]) == None;
    assert find_pos(~"hi", ~[~"foo", ~"bar", ~"baz", ~"hi"]) == Some(3u);

    bail_deep(~[~[false, false], ~[true, true], ~[false, true]]);
    bail_deep(~[~[true]]);
    bail_deep(~[~[false, false, false]]);

    assert ret_deep() == ~"hi";
}
<commit_msg>Fix test<commit_after>// xfail-fast
#[legacy_modes];

use cmp::Eq;

fn iter<T>(v: ~[T], it: fn(T) -> bool) {
    let mut i = 0u, l = v.len();
    while i < l {
        if !it(v[i]) { break; }
        i += 1u;
    }
}

fn find_pos<T:Eq Copy>(n: T, h: ~[T]) -> Option<uint> {
    let mut i = 0u;
    for iter(copy h) |e| {
        if e == n { return Some(i); }
        i += 1u;
    }
    None
}

fn bail_deep(x: ~[~[bool]]) {
    let mut seen = false;
    for iter(copy x) |x| {
        for iter(copy x) |x| {
            assert !seen;
            if x { seen = true; return; }
        }
    }
    assert !seen;
}

fn ret_deep() -> ~str {
    for iter(~[1, 2]) |e| {
        for iter(~[3, 4]) |x| {
            if e + x > 4 { return ~"hi"; }
        }
    }
    return ~"bye";
}

fn main() {
    let mut last = 0;
    for vec::all(~[1, 2, 3, 4, 5, 6, 7]) |e| {
        last = *e;
        if *e == 5 { break; }
        if *e % 2 == 1 { loop; }
        assert *e % 2 == 0;
    };
    assert last == 5;

    assert find_pos(1, ~[0, 1, 2, 3]) == Some(1u);
    assert find_pos(1, ~[0, 4, 2, 3]) == None;
    assert find_pos(~"hi", ~[~"foo", ~"bar", ~"baz", ~"hi"]) == Some(3u);

    bail_deep(~[~[false, false], ~[true, true], ~[false, true]]);
    bail_deep(~[~[true]]);
    bail_deep(~[~[false, false, false]]);

    assert ret_deep() == ~"hi";
}
<|endoftext|>


<commit_before>use crate::math::{Isometry, Point, Vector, DIM};
use crate::query::{PointProjection, PointQuery, PointQueryWithLocation};
use crate::shape::{FeatureId, Triangle, TrianglePointLocation};
use na::{self, RealField};

#[inline]
fn compute_result<N: RealField>(pt: &Point<N>, proj: Point<N>) -> PointProjection<N> {
    #[cfg(feature = "dim2")]
    {
        PointProjection::new(*pt == proj, proj)
    }

    #[cfg(feature = "dim3")]
    {
        // FIXME: is this acceptable to assume the point is inside of the
        // triangle if it is close enough?
        PointProjection::new(relative_eq!(proj, *pt), proj)
    }
}

impl<N: RealField> PointQuery<N> for Triangle<N> {
    #[inline]
    fn project_point(&self, m: &Isometry<N>, pt: &Point<N>, solid: bool) -> PointProjection<N> {
        let (projection, _) = self.project_point_with_location(m, pt, solid);
        projection
    }

    #[inline]
    fn project_point_with_feature(
        &self,
        m: &Isometry<N>,
        pt: &Point<N>,
    ) -> (PointProjection<N>, FeatureId) {
        let (proj, loc) = if DIM == 2 {
            self.project_point_with_location(m, pt, false)
        } else {
            self.project_point_with_location(m, pt, true)
        };

        let feature = match loc {
            TrianglePointLocation::OnVertex(i) => FeatureId::Vertex(i),
            #[cfg(feature = "dim3")]
            TrianglePointLocation::OnEdge(i, _) => FeatureId::Edge(i),
            #[cfg(feature = "dim2")]
            TrianglePointLocation::OnEdge(i, _) => FeatureId::Face(i),
            TrianglePointLocation::OnFace(i, _) => FeatureId::Face(i),
            TrianglePointLocation::OnSolid => FeatureId::Face(0),
        };

        (proj, feature)
    }

    // NOTE: the default implementation of `.distance_to_point(...)` will return the error that was
    // eaten by the `::approx_eq(...)` on `project_point(...)`.
}

impl<N: RealField> PointQueryWithLocation<N> for Triangle<N> {
    type Location = TrianglePointLocation<N>;

    #[inline]
    fn project_point_with_location(
        &self,
        m: &Isometry<N>,
        pt: &Point<N>,
        solid: bool,
    ) -> (PointProjection<N>, Self::Location) {
        let a = *self.a();
        let b = *self.b();
        let c = *self.c();
        let p = m.inverse_transform_point(pt);

        let _1 = na::one::<N>();

        let ab = b - a;
        let ac = c - a;
        let ap = p - a;

        let ab_ap = ab.dot(&ap);
        let ac_ap = ac.dot(&ap);

        if ab_ap <= na::zero() && ac_ap <= na::zero() {
            // Voronoï region of `a`.
            return (
                compute_result(pt, m * a),
                TrianglePointLocation::OnVertex(0),
            );
        }

        let bp = p - b;
        let ab_bp = ab.dot(&bp);
        let ac_bp = ac.dot(&bp);

        if ab_bp >= na::zero() && ac_bp <= ab_bp {
            // Voronoï region of `b`.
            return (
                compute_result(pt, m * b),
                TrianglePointLocation::OnVertex(1),
            );
        }

        let cp = p - c;
        let ab_cp = ab.dot(&cp);
        let ac_cp = ac.dot(&cp);

        if ac_cp >= na::zero() && ab_cp <= ac_cp {
            // Voronoï region of `c`.
            return (
                compute_result(pt, m * c),
                TrianglePointLocation::OnVertex(2),
            );
        }

        enum ProjectionInfo<N> {
            OnAB,
            OnAC,
            OnBC,
            // The usize indicates if we are on the CW side (0) or CCW side (1) of the face.
            OnFace(usize, N, N, N),
        }

        // Checks on which edge voronoï region the point is.
        // For 2D and 3D, it uses explicit cross/perp products that are
        // more numerically stable.
        fn stable_check_edges_voronoi<N: RealField>(
            ab: &Vector<N>,
            ac: &Vector<N>,
            bc: &Vector<N>,
            ap: &Vector<N>,
            bp: &Vector<N>,
            cp: &Vector<N>,
            ab_ap: N,
            ab_bp: N,
            ac_ap: N,
            ac_cp: N,
            ac_bp: N,
            ab_cp: N,
        ) -> ProjectionInfo<N> {
            #[cfg(feature = "dim2")]
            {
                let n = ab.perp(&ac);
                let vc = n * ab.perp(&ap);
                if vc < na::zero() && ab_ap >= na::zero() && ab_bp <= na::zero() {
                    return ProjectionInfo::OnAB;
                }

                let vb = -n * ac.perp(&cp);
                if vb < na::zero() && ac_ap >= na::zero() && ac_cp <= na::zero() {
                    return ProjectionInfo::OnAC;
                }

                let va = n * bc.perp(&bp);
                if va < na::zero() && ac_bp - ab_bp >= na::zero() && ab_cp - ac_cp >= na::zero() {
                    return ProjectionInfo::OnBC;
                }

                return ProjectionInfo::OnFace(0, va, vb, vc);
            }
            #[cfg(feature = "dim3")]
            {
                let n = ab.cross(&ac);
                let vc = n.dot(&ab.cross(&ap));
                if vc < na::zero() && ab_ap >= na::zero() && ab_bp <= na::zero() {
                    return ProjectionInfo::OnAB;
                }

                let vb = -n.dot(&ac.cross(&cp));
                if vb < na::zero() && ac_ap >= na::zero() && ac_cp <= na::zero() {
                    return ProjectionInfo::OnAC;
                }

                let va = n.dot(&bc.cross(&bp));
                if va < na::zero() && ac_bp - ab_bp >= na::zero() && ab_cp - ac_cp >= na::zero() {
                    return ProjectionInfo::OnBC;
                }

                let clockwise = if n.dot(&ap) >= N::zero() { 0 } else { 1 };

                return ProjectionInfo::OnFace(clockwise, va, vb, vc);
            }
        }

        let bc = c - b;
        match stable_check_edges_voronoi(
            &ab, &ac, &bc, &ap, &bp, &cp, ab_ap, ab_bp, ac_ap, ac_cp, ac_bp, ab_cp,
        ) {
            ProjectionInfo::OnAB => {
                // Voronoï region of `ab`.
                let v = ab_ap / ab.norm_squared();
                let bcoords = [_1 - v, v];

                let res = a + ab * v;
                return (
                    compute_result(pt, m * res),
                    TrianglePointLocation::OnEdge(0, bcoords),
                );
            }
            ProjectionInfo::OnAC => {
                // Voronoï region of `ac`.
                let w = ac_ap / ac.norm_squared();
                let bcoords = [_1 - w, w];

                let res = a + ac * w;
                return (
                    compute_result(pt, m * res),
                    TrianglePointLocation::OnEdge(2, bcoords),
                );
            }
            ProjectionInfo::OnBC => {
                // Voronoï region of `bc`.
                let w = bc.dot(&bp) / bc.norm_squared();
                let bcoords = [_1 - w, w];

                let res = b + bc * w;
                return (
                    compute_result(pt, m * res),
                    TrianglePointLocation::OnEdge(1, bcoords),
                );
            }
            ProjectionInfo::OnFace(face_side, va, vb, vc) => {
                // Voronoï region of the face.
                if DIM != 2 {
                    // NOTE: in some cases, numerical instability
                    // may result in the denominator being zero
                    // when the triangle is nearly degenerate.
                    if va + vb + vc != N::zero() {
                        let denom = _1 / (va + vb + vc);
                        let v = vb * denom;
                        let w = vc * denom;
                        let bcoords = [_1 - v - w, v, w];
                        let res = a + ab * v + ac * w;

                        return (
                            compute_result(pt, m * res),
                            TrianglePointLocation::OnFace(face_side, bcoords),
                        );
                    }
                }
            }
        }

        // Special treatement if we work in 2d because in this case we really are inside of the
        // object.
        if solid {
            (
                PointProjection::new(true, *pt),
                TrianglePointLocation::OnSolid,
            )
        } else {
            // We have to project on the closest edge.

            // FIXME: this might be optimizable.
            // FIXME: be careful with numerical errors.
            let v = ab_ap / (ab_ap - ab_bp); // proj on ab = a + ab * v
            let w = ac_ap / (ac_ap - ac_cp); // proj on ac = a + ac * w
            let u = (ac_bp - ab_bp) / (ac_bp - ab_bp + ab_cp - ac_cp); // proj on bc = b + bc * u

            let bc = c - b;
            let d_ab = ap.norm_squared() - (ab.norm_squared() * v * v);
            let d_ac = ap.norm_squared() - (ac.norm_squared() * u * u);
            let d_bc = bp.norm_squared() - (bc.norm_squared() * w * w);

            let mut proj;
            let loc;

            if d_ab < d_ac {
                if d_ab < d_bc {
                    // ab
                    let bcoords = [_1 - v, v];
                    proj = a + ab * v;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(0, bcoords);
                } else {
                    // bc
                    let bcoords = [_1 - u, u];
                    proj = b + bc * u;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(1, bcoords);
                }
            } else {
                if d_ac < d_bc {
                    // ac
                    let bcoords = [_1 - w, w];
                    proj = a + ac * w;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(2, bcoords);
                } else {
                    // bc
                    let bcoords = [_1 - u, u];
                    proj = b + bc * u;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(1, bcoords);
                }
            }

            (PointProjection::new(true, proj), loc)
        }
    }
}
<commit_msg>Fix numerical instability in point-triangle projection in 3D when using fixed-point numbers.<commit_after>use crate::math::{Isometry, Point, Vector, DIM};
use crate::query::{PointProjection, PointQuery, PointQueryWithLocation};
use crate::shape::{FeatureId, Triangle, TrianglePointLocation};
use na::{self, RealField};

#[inline]
fn compute_result<N: RealField>(pt: &Point<N>, proj: Point<N>) -> PointProjection<N> {
    #[cfg(feature = "dim2")]
    {
        PointProjection::new(*pt == proj, proj)
    }

    #[cfg(feature = "dim3")]
    {
        // FIXME: is this acceptable to assume the point is inside of the
        // triangle if it is close enough?
        PointProjection::new(relative_eq!(proj, *pt), proj)
    }
}

impl<N: RealField> PointQuery<N> for Triangle<N> {
    #[inline]
    fn project_point(&self, m: &Isometry<N>, pt: &Point<N>, solid: bool) -> PointProjection<N> {
        let (projection, _) = self.project_point_with_location(m, pt, solid);
        projection
    }

    #[inline]
    fn project_point_with_feature(
        &self,
        m: &Isometry<N>,
        pt: &Point<N>,
    ) -> (PointProjection<N>, FeatureId) {
        let (proj, loc) = if DIM == 2 {
            self.project_point_with_location(m, pt, false)
        } else {
            self.project_point_with_location(m, pt, true)
        };

        let feature = match loc {
            TrianglePointLocation::OnVertex(i) => FeatureId::Vertex(i),
            #[cfg(feature = "dim3")]
            TrianglePointLocation::OnEdge(i, _) => FeatureId::Edge(i),
            #[cfg(feature = "dim2")]
            TrianglePointLocation::OnEdge(i, _) => FeatureId::Face(i),
            TrianglePointLocation::OnFace(i, _) => FeatureId::Face(i),
            TrianglePointLocation::OnSolid => FeatureId::Face(0),
        };

        (proj, feature)
    }

    // NOTE: the default implementation of `.distance_to_point(...)` will return the error that was
    // eaten by the `::approx_eq(...)` on `project_point(...)`.
}

impl<N: RealField> PointQueryWithLocation<N> for Triangle<N> {
    type Location = TrianglePointLocation<N>;

    #[inline]
    fn project_point_with_location(
        &self,
        m: &Isometry<N>,
        pt: &Point<N>,
        solid: bool,
    ) -> (PointProjection<N>, Self::Location) {
        let a = *self.a();
        let b = *self.b();
        let c = *self.c();
        let p = m.inverse_transform_point(pt);

        let _1 = na::one::<N>();

        let ab = b - a;
        let ac = c - a;
        let ap = p - a;

        let ab_ap = ab.dot(&ap);
        let ac_ap = ac.dot(&ap);

        if ab_ap <= na::zero() && ac_ap <= na::zero() {
            // Voronoï region of `a`.
            return (
                compute_result(pt, m * a),
                TrianglePointLocation::OnVertex(0),
            );
        }

        let bp = p - b;
        let ab_bp = ab.dot(&bp);
        let ac_bp = ac.dot(&bp);

        if ab_bp >= na::zero() && ac_bp <= ab_bp {
            // Voronoï region of `b`.
            return (
                compute_result(pt, m * b),
                TrianglePointLocation::OnVertex(1),
            );
        }

        let cp = p - c;
        let ab_cp = ab.dot(&cp);
        let ac_cp = ac.dot(&cp);

        if ac_cp >= na::zero() && ab_cp <= ac_cp {
            // Voronoï region of `c`.
            return (
                compute_result(pt, m * c),
                TrianglePointLocation::OnVertex(2),
            );
        }

        enum ProjectionInfo<N> {
            OnAB,
            OnAC,
            OnBC,
            // The usize indicates if we are on the CW side (0) or CCW side (1) of the face.
            OnFace(usize, N, N, N),
        }

        // Checks on which edge voronoï region the point is.
        // For 2D and 3D, it uses explicit cross/perp products that are
        // more numerically stable.
        fn stable_check_edges_voronoi<N: RealField>(
            ab: &Vector<N>,
            ac: &Vector<N>,
            bc: &Vector<N>,
            ap: &Vector<N>,
            bp: &Vector<N>,
            cp: &Vector<N>,
            ab_ap: N,
            ab_bp: N,
            ac_ap: N,
            ac_cp: N,
            ac_bp: N,
            ab_cp: N,
        ) -> ProjectionInfo<N> {
            #[cfg(feature = "dim2")]
            {
                let n = ab.perp(&ac);
                let vc = n * ab.perp(&ap);
                if vc < na::zero() && ab_ap >= na::zero() && ab_bp <= na::zero() {
                    return ProjectionInfo::OnAB;
                }

                let vb = -n * ac.perp(&cp);
                if vb < na::zero() && ac_ap >= na::zero() && ac_cp <= na::zero() {
                    return ProjectionInfo::OnAC;
                }

                let va = n * bc.perp(&bp);
                if va < na::zero() && ac_bp - ab_bp >= na::zero() && ab_cp - ac_cp >= na::zero() {
                    return ProjectionInfo::OnBC;
                }

                return ProjectionInfo::OnFace(0, va, vb, vc);
            }
            #[cfg(feature = "dim3")]
            {
                let n;

                #[cfg(feature = "improved_fixed_point_support")]
                {
                    let scaled_n = ab.cross(&ac);
                    n = scaled_n.try_normalize(N::zero()).unwrap_or(scaled_n);
                }

                #[cfg(not(feature = "improved_fixed_point_support"))]
                {
                    n = ab.cross(&ac);
                }

                let vc = n.dot(&ab.cross(&ap));
                if vc < na::zero() && ab_ap >= na::zero() && ab_bp <= na::zero() {
                    return ProjectionInfo::OnAB;
                }

                let vb = -n.dot(&ac.cross(&cp));
                if vb < na::zero() && ac_ap >= na::zero() && ac_cp <= na::zero() {
                    return ProjectionInfo::OnAC;
                }

                let va = n.dot(&bc.cross(&bp));
                if va < na::zero() && ac_bp - ab_bp >= na::zero() && ab_cp - ac_cp >= na::zero() {
                    return ProjectionInfo::OnBC;
                }

                let clockwise = if n.dot(&ap) >= N::zero() { 0 } else { 1 };

                return ProjectionInfo::OnFace(clockwise, va, vb, vc);
            }
        }

        let bc = c - b;
        match stable_check_edges_voronoi(
            &ab, &ac, &bc, &ap, &bp, &cp, ab_ap, ab_bp, ac_ap, ac_cp, ac_bp, ab_cp,
        ) {
            ProjectionInfo::OnAB => {
                // Voronoï region of `ab`.
                let v = ab_ap / ab.norm_squared();
                let bcoords = [_1 - v, v];

                let res = a + ab * v;
                return (
                    compute_result(pt, m * res),
                    TrianglePointLocation::OnEdge(0, bcoords),
                );
            }
            ProjectionInfo::OnAC => {
                // Voronoï region of `ac`.
                let w = ac_ap / ac.norm_squared();
                let bcoords = [_1 - w, w];

                let res = a + ac * w;
                return (
                    compute_result(pt, m * res),
                    TrianglePointLocation::OnEdge(2, bcoords),
                );
            }
            ProjectionInfo::OnBC => {
                // Voronoï region of `bc`.
                let w = bc.dot(&bp) / bc.norm_squared();
                let bcoords = [_1 - w, w];

                let res = b + bc * w;
                return (
                    compute_result(pt, m * res),
                    TrianglePointLocation::OnEdge(1, bcoords),
                );
            }
            ProjectionInfo::OnFace(face_side, va, vb, vc) => {
                // Voronoï region of the face.
                if DIM != 2 {
                    // NOTE: in some cases, numerical instability
                    // may result in the denominator being zero
                    // when the triangle is nearly degenerate.
                    if va + vb + vc != N::zero() {
                        let denom = _1 / (va + vb + vc);
                        let v = vb * denom;
                        let w = vc * denom;
                        let bcoords = [_1 - v - w, v, w];
                        let res = a + ab * v + ac * w;

                        return (
                            compute_result(pt, m * res),
                            TrianglePointLocation::OnFace(face_side, bcoords),
                        );
                    }
                }
            }
        }

        // Special treatement if we work in 2d because in this case we really are inside of the
        // object.
        if solid {
            (
                PointProjection::new(true, *pt),
                TrianglePointLocation::OnSolid,
            )
        } else {
            // We have to project on the closest edge.

            // FIXME: this might be optimizable.
            // FIXME: be careful with numerical errors.
            let v = ab_ap / (ab_ap - ab_bp); // proj on ab = a + ab * v
            let w = ac_ap / (ac_ap - ac_cp); // proj on ac = a + ac * w
            let u = (ac_bp - ab_bp) / (ac_bp - ab_bp + ab_cp - ac_cp); // proj on bc = b + bc * u

            let bc = c - b;
            let d_ab = ap.norm_squared() - (ab.norm_squared() * v * v);
            let d_ac = ap.norm_squared() - (ac.norm_squared() * u * u);
            let d_bc = bp.norm_squared() - (bc.norm_squared() * w * w);

            let mut proj;
            let loc;

            if d_ab < d_ac {
                if d_ab < d_bc {
                    // ab
                    let bcoords = [_1 - v, v];
                    proj = a + ab * v;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(0, bcoords);
                } else {
                    // bc
                    let bcoords = [_1 - u, u];
                    proj = b + bc * u;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(1, bcoords);
                }
            } else {
                if d_ac < d_bc {
                    // ac
                    let bcoords = [_1 - w, w];
                    proj = a + ac * w;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(2, bcoords);
                } else {
                    // bc
                    let bcoords = [_1 - u, u];
                    proj = b + bc * u;
                    proj = m * proj;
                    loc = TrianglePointLocation::OnEdge(1, bcoords);
                }
            }

            (PointProjection::new(true, proj), loc)
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

struct Watcher<T> {
    inner: T,
    callbacks: HashSet<fn(T)>
}
<commit_msg>Add fn new<commit_after>use std::collections::HashSet;

struct Watcher<T> {
    value: T,
    callbacks: HashSet<fn(T)>
}

impl<T> Watcher<T> {
    pub fn new(value: T) -> Watcher<T> {
        Watcher {
            value: value,
            callbacks: HashSet::new()
        }
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Components are functions
//!
//! We can treat a component as a pair of functions: one to send data to it, and one to retrieve its
//! current status. This can be a convenient way to try them out.
//!
//! Components are asynchronous: they can receive or publish new results at any time. To accomodate this,
//! when a component is converted into a functional form, two functions result: `send()` to send data to
//! the component and `recv()` to retrieve the component's current state.
//!
//! # Example
//!
//! Here's the definition of a component that adds two numbers together:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct InputTree {
//!     a: i32,
//!     b: i32,
//! };
//! impl EncodeToTreeNode for InputTree { }
//!
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct ResultTree {
//!     result: i32
//! };
//! impl EncodeToTreeNode for ResultTree { }
//!
//! let component = component_fn(|input: &InputTree| {
//!    ResultTree { result: input.a + input.b }
//! });
//! # }
//! ```
//!
//! We can call `ComponentEndPoint::<InputTree, ResultTree>::new(component)` to turn this into
//! a pair of functions that are convenient to call:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! let mut endpoint = ComponentEndPoint::<InputTree, ResultTree>::new(component);
//!
//! endpoint.send(InputTree { a: 4, b: 7 });
//! let result_tree = endpoint.recv();  // == Some({ result: 11 }) as this component updates immediately
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//!
//! ```

use std::marker::PhantomData;

use super::super::tree::*;
use super::component::*;
use super::immediate_publisher::*;
use super::output_tree_publisher::*;

///
/// A component endpoint provides a basic input/output interface to a component, allowing data to be sent to it
/// and its output retrieved.
///
pub struct ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    _component: ComponentRef,
    reader:     Box<Fn() -> TreeRef>,
    input:      PublisherRef,

    phantom_in: PhantomData<TIn>,
    phantom_out: PhantomData<TOut>
}

impl<TIn, TOut> ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    ///
    /// Creates a new endpoint from an object that can create a component
    ///
    pub fn new<TComponent: ConvertToComponent>(component: TComponent) -> ComponentEndPoint<TIn, TOut> {
        let input       = ImmediatePublisher::new();
        let consumer    = input.create_consumer();
        let output      = OutputTreePublisher::new();
        let reader      = output.get_tree_reader();

        let component   = component.into_component(consumer, output);

        ComponentEndPoint { _component: component, reader: reader, input: input, phantom_in: PhantomData, phantom_out: PhantomData }
    }

    ///
    /// Sends new data to the component
    ///
    #[inline]
    pub fn send(&mut self, data: TIn) {
        self.input.publish(TreeChange::new(&(), TreeChangeType::Child, Some(&data.to_tree_node())));
    }

    ///
    /// Retrieves the current state of the component's output
    ///
    /// If the output does not conform to the type `TOut`, then this will return `None`
    ///
    #[inline]
    pub fn recv(&self) -> Option<TOut> {
        let reader = &self.reader;

        TOut::new_from_tree(&reader()).ok()
    }
}
<commit_msg>Add a way to turn ConsumerRef's into funtions<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Components are functions
//!
//! We can treat a component as a pair of functions: one to send data to it, and one to retrieve its
//! current status. This can be a convenient way to try them out.
//!
//! Components are asynchronous: they can receive or publish new results at any time. To accomodate this,
//! when a component is converted into a functional form, two functions result: `send()` to send data to
//! the component and `recv()` to retrieve the component's current state.
//!
//! # Endpoints
//!
//! Endpoints can be used to retrieve both a sending and a receiving function for a component.
//!
//! ## Example
//!
//! Here's the definition of a component that adds two numbers together:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct InputTree {
//!     a: i32,
//!     b: i32,
//! };
//! impl EncodeToTreeNode for InputTree { }
//!
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct ResultTree {
//!     result: i32
//! };
//! impl EncodeToTreeNode for ResultTree { }
//!
//! let component = component_fn(|input: &InputTree| {
//!    ResultTree { result: input.a + input.b }
//! });
//! # }
//! ```
//!
//! We can call `ComponentEndPoint::<InputTree, ResultTree>::new(component)` to turn this into
//! a pair of functions that are convenient to call:
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! let mut endpoint = ComponentEndPoint::<InputTree, ResultTree>::new(component);
//!
//! endpoint.send(InputTree { a: 4, b: 7 });
//! let result_tree = endpoint.recv();  // == Some({ result: 11 }) as this component updates immediately
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//! ```
//!
//! # Receiver functions
//!
//! This adds the ability to call get_receiver() with a type on any consumer in order to create a function
//! that can be called to retrieve its current value as a tree or any object that can be decoded from a
//! tree.
//!
//! ## Example
//!
//! ```
//! # extern crate tametree;
//! # extern crate rustc_serialize;
//! # fn main() {
//! # use tametree::component::*;
//! # use tametree::component::immediate_publisher::*;
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct InputTree {
//! #     a: i32,
//! #     b: i32,
//! # };
//! # impl EncodeToTreeNode for InputTree { }
//! #
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct ResultTree {
//! #     result: i32
//! # };
//! # impl EncodeToTreeNode for ResultTree { }
//! #
//! # let component = component_fn(|input: &InputTree| {
//! #    ResultTree { result: input.a + input.b }
//! # });
//! #
//! # let mut publisher         = ImmediatePublisher::new();
//! # let mut input_consumer    = publisher.create_consumer();
//! # let mut output_publisher  = ImmediatePublisher::new();
//! # let mut consumer          = output_publisher.create_consumer();
//! # let _active_component     = component.into_component(input_consumer, output_publisher);
//! let mut receiver: RecvFn<ResultTree> = consumer.get_receiver();
//!
//! publisher.publish(TreeChange::new(&(), TreeChangeType::Child, Some(&InputTree { a: 4, b: 7 }.to_tree_node())));
//! let result_tree = receiver();           // == Some(12) for our test component
//! # assert!(result_tree.unwrap().result == 11);
//! # }
//!
//! ```

use std::rc::*;
use std::marker::PhantomData;

use super::super::tree::*;
use super::super::util::clonecell::*;
use super::component::*;
use super::immediate_publisher::*;
use super::output_tree_publisher::*;

///
/// Defines the type of a receiver function
///
pub type RecvFn<TOut> = Box<Fn() -> Option<TOut>>;

///
/// Trait implemented by objects that can call a receiving function
///
pub trait Receiver<TOut> {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> RecvFn<TOut>;
}

impl Receiver<TreeRef> for ConsumerRef {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> RecvFn<TreeRef> {
        let tree        = Rc::new(CloneCell::new("".to_tree_node()));
        let also_tree   = tree.clone();

        self.subscribe(TreeAddress::Here, TreeExtent::SubTree, Box::new(move |change| {
            let current_tree = (*tree).get();
            let altered_tree = change.apply(&current_tree);
            (*tree).set(altered_tree);
        }));

        Box::new(move || {
            Some((*also_tree).get())
        })
    }
}

impl<TOut: 'static + DecodeFromTreeNode + Sized> Receiver<TOut> for ConsumerRef {
    ///
    /// Retrieves a function that can be used to get the last known value of this receiver (or `None` if it can't be converted to `TOut`)
    ///
    fn get_receiver(&mut self) -> Box<Fn() -> Option<TOut>> {
        let tree_receiver: Box<Fn() -> Option<TreeRef>> = self.get_receiver();

        Box::new(move || {
            if let Some(tree) = tree_receiver() {
                if let Ok(result) = TOut::new_from_tree(&tree) {
                    Some(result)
                } else {
                    None
                }
            } else {
                None
            }
        })
    }
}

///
/// A component endpoint provides a basic input/output interface to a component, allowing data to be sent to it
/// and its output retrieved.
///
pub struct ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    _component: ComponentRef,
    reader:     Box<Fn() -> TreeRef>,
    input:      PublisherRef,

    phantom_in: PhantomData<TIn>,
    phantom_out: PhantomData<TOut>
}

impl<TIn, TOut> ComponentEndPoint<TIn, TOut>
    where   TIn: 'static + ToTreeNode,
            TOut: 'static + DecodeFromTreeNode {
    ///
    /// Creates a new endpoint from an object that can create a component
    ///
    pub fn new<TComponent: ConvertToComponent>(component: TComponent) -> ComponentEndPoint<TIn, TOut> {
        let input       = ImmediatePublisher::new();
        let consumer    = input.create_consumer();
        let output      = OutputTreePublisher::new();
        let reader      = output.get_tree_reader();

        let component   = component.into_component(consumer, output);

        ComponentEndPoint { _component: component, reader: reader, input: input, phantom_in: PhantomData, phantom_out: PhantomData }
    }

    ///
    /// Sends new data to the component
    ///
    #[inline]
    pub fn send(&mut self, data: TIn) {
        self.input.publish(TreeChange::new(&(), TreeChangeType::Child, Some(&data.to_tree_node())));
    }

    ///
    /// Retrieves the current state of the component's output
    ///
    /// If the output does not conform to the type `TOut`, then this will return `None`
    ///
    #[inline]
    pub fn recv(&self) -> Option<TOut> {
        let reader = &self.reader;

        TOut::new_from_tree(&reader()).ok()
    }
}
<|endoftext|>


<commit_before>use std::cmp::min;
use std::env;
use std::fs::{File};
use std::io::{BufReader, BufRead};
use std::str::FromStr;
use std::str::from_utf8;
use std::path::{Path, PathBuf};
use unshare::{Command, Stdio};

use libc::{geteuid, getegid};
use libc::{uid_t, gid_t};

use config::Range;
use config::Settings;
use self::Uidmap::*;
use process_util::{env_path_find, capture_stdout};

#[derive(Clone)]
pub enum Uidmap {
    Singleton(uid_t, gid_t),
    Ranges(Vec<(uid_t, uid_t, uid_t)>, Vec<(gid_t, gid_t, gid_t)>),
}

fn read_uid_map(username: &str) -> Result<Vec<Range>,String> {
    let file = try_msg!(File::open(&Path::new("/etc/subuid")),
        "Can't open /etc/subuid: {err}");
    let mut res = Vec::new();
    let reader = BufReader::new(file);
    for (num, line) in reader.lines().enumerate() {
        let line = try_msg!(line, "Error reading /etc/subuid: {err}");
        let parts: Vec<&str> = line[..].split(':').collect();
        if parts.len() == 0 || parts[0].trim().starts_with('#') {
            continue;
        }
        if parts.len() != 3 {
            return Err(format!("/etc/subuid:{}: Bad syntax: {:?}",
                num+1, line));
        }
        let start = FromStr::from_str(parts[1]);
        let count: Result<uid_t, _> = FromStr::from_str(parts[2].trim_right());
        if parts.len() != 3 || start.is_err() || count.is_err() {
            return Err(format!("/etc/subuid:{}: Bad syntax: {:?}",
                num+1, line));
        }
        if parts[0].eq(username) {
            let start: uid_t = start.unwrap();
            let end = start + count.unwrap() - 1;
            res.push(Range::new(start, end));
        }
    }
    return Ok(res);
}

fn read_gid_map(username: &str) -> Result<Vec<Range>,String> {
    let file = try_msg!(File::open(&Path::new("/etc/subgid")),
        "Can't open /etc/subgid: {err}");
    let mut res = Vec::new();
    let reader = BufReader::new(file);
    for (num, line) in reader.lines().enumerate() {
        let line = try_msg!(line, "Error reading /etc/subgid: {err}");
        let parts: Vec<&str> = line[..].split(':').collect();
        if parts.len() == 0 || parts[0].trim().starts_with('#') {
            continue;
        }
        if parts.len() != 3 {
            return Err(format!("/etc/subgid:{}: Bad syntax: {:?}",
                num+1, line));
        }
        let start = FromStr::from_str(parts[1]);
        let count: Result<uid_t, _> = FromStr::from_str(parts[2].trim_right());
        if parts.len() != 3 || start.is_err() || count.is_err() {
            return Err(format!("/etc/subgid:{}: Bad syntax", num+1));
        }
        if parts[0].eq(username) {
            let start: gid_t = start.unwrap();
            let end = start + count.unwrap() - 1;
            res.push(Range::new(start, end));
        }
    }
    return Ok(res);
}

pub fn match_ranges(req: &Vec<Range>, allowed: &Vec<Range>, own_id: uid_t)
    -> Result<Vec<(uid_t, uid_t, uid_t)>, ()>
{
    let mut res = vec!((0, own_id, 1));
    let mut reqiter = req.iter();
    let mut reqval = *reqiter.next().unwrap();
    let mut allowiter = allowed.iter();
    let mut allowval = *allowiter.next().unwrap();
    loop {
        if reqval.start() == 0 {
            reqval = reqval.shift(1);
        }
        if allowval.start() == 0 {
            allowval = allowval.shift(1);
        }
        let clen = min(reqval.len(), allowval.len());
        if clen > 0 {
            res.push((reqval.start(), allowval.start(), clen));
        }
        reqval = reqval.shift(clen);
        allowval = allowval.shift(clen);
        if reqval.len() == 0 {
            reqval = match reqiter.next() {
                Some(val) => *val,
                None => break,
            };
        }
        if allowval.len() == 0 {
            allowval = match allowiter.next() {
                Some(val) => *val,
                None => return Err(()),
            };
        }
    }
    return Ok(res);
}

pub fn get_max_uidmap() -> Result<Uidmap, String>
{
    let mut cmd = Command::new(env_path_find("id")
                               .unwrap_or(PathBuf::from("/usr/bin/id")));
    cmd.arg("-u").arg("-n");
    if let Ok(path) = env::var("_VAGGA_PATH") {
        cmd.env("PATH", path);
    }
    cmd.stdin(Stdio::null()).stderr(Stdio::inherit());
    let username = try!(capture_stdout(cmd)
        .map_err(|e| format!("Error running `id -u -n`: {}", e))
        .and_then(|val| from_utf8(&val).map(|x| x.trim().to_string())
                   .map_err(|e| format!("Can't decode username: {}", e))));
    let uid_map = read_uid_map(&username)
        .map_err(|e| error!("Error reading uidmap: {}", e));
    let gid_map = read_gid_map(&username)
        .map_err(|e| error!("Error reading gidmap: {}", e));

    let uid = unsafe { geteuid() };
    let gid = unsafe { getegid() };
    if let (Ok(uid_map), Ok(gid_map)) = (uid_map, gid_map) {
        if uid_map.len() == 0 && gid_map.len() == 0 && uid == 0 {
            let uid_rng = try!(read_uid_ranges("/proc/self/uid_map", true));
            let gid_rng = try!(read_uid_ranges("/proc/self/gid_map", true));
            return Ok(Ranges(
                uid_rng.into_iter()
                    .map(|r| (r.start(), r.start(), r.len())).collect(),
                gid_rng.into_iter()
                    .map(|r| (r.start(), r.start(), r.len())).collect()));
        }
        let mut uids = vec!((0, uid, 1));
        for &rng in uid_map.iter() {
            let mut rng = rng;
            if uid >= rng.start() && uid <= rng.end() {
                // TODO(tailhook) implement better heuristic
                assert!(uid == rng.start());
                rng = rng.shift(1);
                if rng.len() == 0 { continue; }
            }
            uids.push((rng.start(), rng.start(), rng.len()));
        }

        let mut gids = vec!((0, gid, 1));
        for &rng in gid_map.iter() {
            let mut rng = rng;
            if gid >= rng.start() && gid <= rng.end() {
                // TODO(tailhook) implement better heuristic
                assert!(gid == rng.start());
                rng = rng.shift(1);
                if rng.len() == 0 { continue; }
            }
            gids.push((rng.start(), rng.start(), rng.len()));
        }

        return Ok(Ranges(uids, gids));
    } else {
        warn!("Could not read /etc/subuid or /etc/subgid \
            (see http://bit.ly/err_subuid)");
        return Ok(Singleton(uid, gid));
    }
}

fn read_uid_ranges(path: &str, read_inside: bool) -> Result<Vec<Range>, String>
{
    let file = BufReader::new(try!(File::open(&Path::new(path))
        .map_err(|e| format!("Error reading uid/gid map: {}", e))));
    let mut result = vec!();
    for line in file.lines() {
        let line = try!(line
            .map_err(|_| format!("Error reading uid/gid map")));
        let mut words = line[..].split_whitespace();
        let inside: u32 = try!(words.next().and_then(|x| FromStr::from_str(x).ok())
            .ok_or(format!("uid/gid map format error")));
        let outside: u32 = try!(words.next().and_then(|x| FromStr::from_str(x).ok())
            .ok_or(format!("uid/gid map format error")));
        let count: u32 = try!(words.next().and_then(|x| FromStr::from_str(x).ok())
            .ok_or(format!("uid/gid map format error")));
        if read_inside {
            result.push(Range::new(inside, inside+count-1));
        } else {
            result.push(Range::new(outside, outside+count-1));
        }
    }
    return Ok(result);
}

pub fn map_users(settings: &Settings, uids: &Vec<Range>, gids: &Vec<Range>)
    -> Result<Uidmap, String>
{
    let default_uids = vec!(Range::new(0, 0));
    let default_gids = vec!(Range::new(0, 0));
    let uids = if uids.len() > 0 { uids } else { &default_uids };
    let gids = if gids.len() > 0 { gids } else { &default_gids };
    if settings.uid_map.is_none() {
        let ranges = try!(read_uid_ranges("/proc/self/uid_map", true));
        let uid_map = try!(match_ranges(uids, &ranges, 0)
            .map_err(|()| {
                return format!("Number of allowed subuids is too small. \
                    Required {:?}, allowed {:?}. You either need to increase \
                    allowed numbers in /etc/subuid (preferred) or decrease \
                    needed ranges in vagga.yaml by adding `uids` key \
                    to container config", uids, ranges);
            }));
        let ranges = try!(read_uid_ranges("/proc/self/gid_map", true));
        let gid_map = try!(match_ranges(gids, &ranges, 0)
            .map_err(|()| {
                return format!("Number of allowed subgids is too small. \
                    Required {:?}, allowed {:?}. You either need to increase \
                    allowed numbers in /etc/subgid (preferred) or decrease \
                    needed ranges in vagga.yaml by adding `gids` key \
                    to container config", gids, ranges);
            }));
        return Ok(Ranges(uid_map, gid_map));
    } else {
        let &(ref uids, ref gids) = settings.uid_map.as_ref().unwrap();
        return Ok(Ranges(uids.clone(), gids.clone()));
    }
}
<commit_msg>Replaced unwrap call by pattern mathing<commit_after>use std::cmp::min;
use std::env;
use std::fs::{File};
use std::io::{BufReader, BufRead};
use std::str::FromStr;
use std::str::from_utf8;
use std::path::{Path, PathBuf};
use unshare::{Command, Stdio};

use libc::{geteuid, getegid};
use libc::{uid_t, gid_t};

use config::Range;
use config::Settings;
use self::Uidmap::*;
use process_util::{env_path_find, capture_stdout};

#[derive(Clone)]
pub enum Uidmap {
    Singleton(uid_t, gid_t),
    Ranges(Vec<(uid_t, uid_t, uid_t)>, Vec<(gid_t, gid_t, gid_t)>),
}

fn read_uid_map(username: &str) -> Result<Vec<Range>,String> {
    let file = try_msg!(File::open(&Path::new("/etc/subuid")),
        "Can't open /etc/subuid: {err}");
    let mut res = Vec::new();
    let reader = BufReader::new(file);
    for (num, line) in reader.lines().enumerate() {
        let line = try_msg!(line, "Error reading /etc/subuid: {err}");
        let parts: Vec<&str> = line[..].split(':').collect();
        if parts.len() == 0 || parts[0].trim().starts_with('#') {
            continue;
        }
        if parts.len() != 3 {
            return Err(format!("/etc/subuid:{}: Bad syntax: {:?}",
                num+1, line));
        }
        let start = FromStr::from_str(parts[1]);
        let count: Result<uid_t, _> = FromStr::from_str(parts[2].trim_right());
        if parts.len() != 3 || start.is_err() || count.is_err() {
            return Err(format!("/etc/subuid:{}: Bad syntax: {:?}",
                num+1, line));
        }
        if parts[0].eq(username) {
            let start: uid_t = start.unwrap();
            let end = start + count.unwrap() - 1;
            res.push(Range::new(start, end));
        }
    }
    return Ok(res);
}

fn read_gid_map(username: &str) -> Result<Vec<Range>,String> {
    let file = try_msg!(File::open(&Path::new("/etc/subgid")),
        "Can't open /etc/subgid: {err}");
    let mut res = Vec::new();
    let reader = BufReader::new(file);
    for (num, line) in reader.lines().enumerate() {
        let line = try_msg!(line, "Error reading /etc/subgid: {err}");
        let parts: Vec<&str> = line[..].split(':').collect();
        if parts.len() == 0 || parts[0].trim().starts_with('#') {
            continue;
        }
        if parts.len() != 3 {
            return Err(format!("/etc/subgid:{}: Bad syntax: {:?}",
                num+1, line));
        }
        let start = FromStr::from_str(parts[1]);
        let count: Result<uid_t, _> = FromStr::from_str(parts[2].trim_right());
        if parts.len() != 3 || start.is_err() || count.is_err() {
            return Err(format!("/etc/subgid:{}: Bad syntax", num+1));
        }
        if parts[0].eq(username) {
            let start: gid_t = start.unwrap();
            let end = start + count.unwrap() - 1;
            res.push(Range::new(start, end));
        }
    }
    return Ok(res);
}

pub fn match_ranges(req: &Vec<Range>, allowed: &Vec<Range>, own_id: uid_t)
    -> Result<Vec<(uid_t, uid_t, uid_t)>, ()>
{
    let mut res = vec!((0, own_id, 1));
    let mut reqiter = req.iter();
    let mut reqval = *reqiter.next().unwrap();
    let mut allowiter = allowed.iter();
    let mut allowval = *allowiter.next().unwrap();
    loop {
        if reqval.start() == 0 {
            reqval = reqval.shift(1);
        }
        if allowval.start() == 0 {
            allowval = allowval.shift(1);
        }
        let clen = min(reqval.len(), allowval.len());
        if clen > 0 {
            res.push((reqval.start(), allowval.start(), clen));
        }
        reqval = reqval.shift(clen);
        allowval = allowval.shift(clen);
        if reqval.len() == 0 {
            reqval = match reqiter.next() {
                Some(val) => *val,
                None => break,
            };
        }
        if allowval.len() == 0 {
            allowval = match allowiter.next() {
                Some(val) => *val,
                None => return Err(()),
            };
        }
    }
    return Ok(res);
}

pub fn get_max_uidmap() -> Result<Uidmap, String>
{
    let mut cmd = Command::new(env_path_find("id")
                               .unwrap_or(PathBuf::from("/usr/bin/id")));
    cmd.arg("-u").arg("-n");
    if let Ok(path) = env::var("_VAGGA_PATH") {
        cmd.env("PATH", path);
    }
    cmd.stdin(Stdio::null()).stderr(Stdio::inherit());
    let username = try!(capture_stdout(cmd)
        .map_err(|e| format!("Error running `id -u -n`: {}", e))
        .and_then(|val| from_utf8(&val).map(|x| x.trim().to_string())
                   .map_err(|e| format!("Can't decode username: {}", e))));
    let uid_map = read_uid_map(&username)
        .map_err(|e| error!("Error reading uidmap: {}", e));
    let gid_map = read_gid_map(&username)
        .map_err(|e| error!("Error reading gidmap: {}", e));

    let uid = unsafe { geteuid() };
    let gid = unsafe { getegid() };
    if let (Ok(uid_map), Ok(gid_map)) = (uid_map, gid_map) {
        if uid_map.len() == 0 && gid_map.len() == 0 && uid == 0 {
            let uid_rng = try!(read_uid_ranges("/proc/self/uid_map", true));
            let gid_rng = try!(read_uid_ranges("/proc/self/gid_map", true));
            return Ok(Ranges(
                uid_rng.into_iter()
                    .map(|r| (r.start(), r.start(), r.len())).collect(),
                gid_rng.into_iter()
                    .map(|r| (r.start(), r.start(), r.len())).collect()));
        }
        let mut uids = vec!((0, uid, 1));
        for &rng in uid_map.iter() {
            let mut rng = rng;
            if uid >= rng.start() && uid <= rng.end() {
                // TODO(tailhook) implement better heuristic
                assert!(uid == rng.start());
                rng = rng.shift(1);
                if rng.len() == 0 { continue; }
            }
            uids.push((rng.start(), rng.start(), rng.len()));
        }

        let mut gids = vec!((0, gid, 1));
        for &rng in gid_map.iter() {
            let mut rng = rng;
            if gid >= rng.start() && gid <= rng.end() {
                // TODO(tailhook) implement better heuristic
                assert!(gid == rng.start());
                rng = rng.shift(1);
                if rng.len() == 0 { continue; }
            }
            gids.push((rng.start(), rng.start(), rng.len()));
        }

        return Ok(Ranges(uids, gids));
    } else {
        warn!("Could not read /etc/subuid or /etc/subgid \
            (see http://bit.ly/err_subuid)");
        return Ok(Singleton(uid, gid));
    }
}

fn read_uid_ranges(path: &str, read_inside: bool) -> Result<Vec<Range>, String>
{
    let file = BufReader::new(try!(File::open(&Path::new(path))
        .map_err(|e| format!("Error reading uid/gid map: {}", e))));
    let mut result = vec!();
    for line in file.lines() {
        let line = try!(line
            .map_err(|_| format!("Error reading uid/gid map")));
        let mut words = line[..].split_whitespace();
        let inside: u32 = try!(words.next().and_then(|x| FromStr::from_str(x).ok())
            .ok_or(format!("uid/gid map format error")));
        let outside: u32 = try!(words.next().and_then(|x| FromStr::from_str(x).ok())
            .ok_or(format!("uid/gid map format error")));
        let count: u32 = try!(words.next().and_then(|x| FromStr::from_str(x).ok())
            .ok_or(format!("uid/gid map format error")));
        if read_inside {
            result.push(Range::new(inside, inside+count-1));
        } else {
            result.push(Range::new(outside, outside+count-1));
        }
    }
    return Ok(result);
}

pub fn map_users(settings: &Settings, uids: &Vec<Range>, gids: &Vec<Range>)
    -> Result<Uidmap, String>
{
    let default_uids = vec!(Range::new(0, 0));
    let default_gids = vec!(Range::new(0, 0));
    let uids = if uids.len() > 0 { uids } else { &default_uids };
    let gids = if gids.len() > 0 { gids } else { &default_gids };
    match settings.uid_map {
        None => {
            let ranges = try!(read_uid_ranges("/proc/self/uid_map", true));
            let uid_map = try!(match_ranges(uids, &ranges, 0)
                .map_err(|()| {
                    return format!("Number of allowed subuids is too small. \
                        Required {:?}, allowed {:?}. You either need to increase \
                        allowed numbers in /etc/subuid (preferred) or decrease \
                        needed ranges in vagga.yaml by adding `uids` key \
                        to container config", uids, ranges);
                }));
            let ranges = try!(read_uid_ranges("/proc/self/gid_map", true));
            let gid_map = try!(match_ranges(gids, &ranges, 0)
                .map_err(|()| {
                    return format!("Number of allowed subgids is too small. \
                        Required {:?}, allowed {:?}. You either need to increase \
                        allowed numbers in /etc/subgid (preferred) or decrease \
                        needed ranges in vagga.yaml by adding `gids` key \
                        to container config", gids, ranges);
                }));
            Ok(Ranges(uid_map, gid_map))
        },
        Some((ref uids, ref gids)) => {
            Ok(Ranges(uids.clone(), gids.clone()))
        }
    }
}
<|endoftext|>