<commit_before>use std::io::Write;
use std::io;
use std::str;

use utils::{find_byte};

#[derive(Debug, PartialEq, Eq)]
pub struct Msg {
    pub pfx     : Option<Pfx>,
    pub cmd     : Cmd,
    pub params  : Vec<Vec<u8>>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Pfx {
    Server(String),

    User {
        nick : String,
        /// user@host
        user : String,
    },
}

impl Pfx {
    #[inline]
    pub fn is_server_pfx(&self) -> bool {
        match self {
            &Pfx::Server(_) => true,
            _ => false,
        }
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum Cmd {
    Str(String),
    Num(u16),
}

impl Msg {
    /// Parse a complete IRC message. NOTE: The string should NOT have CR-NL.
    pub fn parse(msg : &[u8]) -> Result<Msg, String> {

        writeln!(&mut io::stderr(), "parsing msg: {:?}", String::from_utf8(msg.to_owned())).unwrap();

        if msg.len() == 0 {
            return Err("Empty msg".to_owned());
        }

        let mut slice = msg;

        let pfx : Option<Pfx> = {
            if msg[0] == b':' {
                // parse prefix
                let ws_idx = find_byte(slice, b' ').unwrap();
                let (mut pfx, slice_) = slice.split_at(ws_idx);
                // drop the : from pfx
                pfx = &pfx[ 1 .. ];
                slice = &slice_[ 1 .. ]; // drop the space
                Some(parse_pfx(&pfx))
            } else {
                // log_stderr_bytes("Can't parse msg prefix:", msg);
                None
            }
        };

        let cmd : Cmd = {
            let ws_idx = find_byte(slice, b' ').unwrap();
            let (cmd, slice_) = slice.split_at(ws_idx);
            slice = &slice_[ 1 .. ]; // drop the space
            match reply_num(cmd) {
                None => Cmd::Str(unsafe {
                    // Cmd strings are added by the server and they're always
                    // ASCII strings, so this is safe and O(1).
                    String::from_utf8_unchecked(cmd.to_owned())
                }),
                Some(num) => Cmd::Num(num)
            }
        };

        let params = try!(parse_params(slice));

        Ok(Msg {
            pfx: pfx,
            cmd: cmd,
            params: params,
        })
    }

    ////////////////////////////////////////////////////////////////////////////
    // Message generation

    pub fn user<W : Write>(hostname : &str, realname : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "USER {} 0 * :{}\r\n", hostname, realname)
    }

    pub fn nick<W : Write>(arg : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "NICK {}\r\n", arg)
    }

    pub fn pong<W : Write>(arg : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "PONG {}\r\n", arg)
    }

    pub fn join<W : Write>(channel : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "JOIN {}\r\n", channel)
    }

    pub fn privmsg<W : Write>(msgtarget : &str, msg : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "PRIVMSG {} {}\r\n", msgtarget, msg)
    }

    pub fn quit<W : Write>(msg : Option<&str>, mut sink : W) -> io::Result<()> {
        match msg {
            None => write!(sink, "QUIT\r\n"),
            Some(msg) => write!(sink, "QUIT {}\r\n", msg)
        }
    }
}

fn reply_num(bs : &[u8]) -> Option<u16> {
    if bs.len() == 3 {
        let n3 = unsafe { *bs.get_unchecked(0) };
        let n2 = unsafe { *bs.get_unchecked(1) };
        let n1 = unsafe { *bs.get_unchecked(2) };
        if is_num_ascii(n3) && is_num_ascii(n2) && is_num_ascii(n1) {
            return Some(((n3 - b'0') as u16) * 100 +
                        ((n2 - b'0') as u16) * 10  +
                        ((n1 - b'0') as u16));
        }
    }
    None
}

#[inline]
fn is_num_ascii(b : u8) -> bool {
    b >= b'0' && b <= b'9'
}

fn parse_pfx(pfx : &[u8]) -> Pfx {
    match find_byte(pfx, b'!') {
        None => Pfx::Server(unsafe { str::from_utf8_unchecked(pfx).to_owned() }),
        Some(idx) => {
            Pfx::User {
                nick: unsafe { str::from_utf8_unchecked(&pfx[ 0 .. idx ]).to_owned() },
                user: unsafe { str::from_utf8_unchecked(&pfx[ idx + 1 .. ]).to_owned() }
            }
        }
    }
}

fn parse_params(chrs : &[u8]) -> Result<Vec<Vec<u8>>, String> {
    if chrs.len() == 0 {
        return Err("parse_params: Empty slice of chars".to_owned());
    }

    let mut ret : Vec<Vec<u8>> = Vec::new();

    let mut current_param = Vec::new();
    for byte_idx in 0 .. chrs.len() {
        let byte = *unsafe { chrs.get_unchecked(byte_idx) };
        if byte == b':' {
            current_param.extend_from_slice(&chrs[ byte_idx + 1 .. ]);
            ret.push(current_param);
            return Ok(ret);
        } else if byte == b' ' {
            ret.push(current_param);
            current_param = Vec::new();
        } else {
            current_param.push(byte);
        }
    }

    if current_param.len() > 0 {
        ret.push(current_param);
    }

    Ok(ret)
}

////////////////////////////////////////////////////////////////////////////////

#[test]
fn parse_error_1() {
    let msg = b"ERROR :Closing Link: 127.0.0.1 (Client Quit)";
    assert!(Msg::parse(msg).is_ok());
}

#[test]
fn parse_error_2() {
    let msg = b":tiny_test!~tiny@213.153.193.52 JOIN #haskell";
    assert_eq!(Msg::parse(msg), Ok(Msg {
        pfx: Some(Pfx::User {
            nick: "tiny_test".to_string(),
            user: "~tiny@213.153.193.52".to_string(),
        }),
        cmd: Cmd::Str("JOIN".to_string()),
        params: vec![
            (Box::new(*b"#haskell") as Box<[u8]>).into_vec()
        ]
    }));
}

#[test]
fn parse_error_3() {
    let msg = b":verne.freenode.net NOTICE * :*** Couldn\'t look up your hostname";
    assert_eq!(Msg::parse(msg), Ok(Msg {
        pfx: Some(Pfx::Server("verne.freenode.net".to_owned())),
        cmd: Cmd::Str("NOTICE".to_owned()),
        params: vec![
            (Box::new(*b"*") as Box<[u8]>).into_vec(),
            (Box::new(*b"*** Couldn\'t look up your hostname") as Box<[u8]>).into_vec()
        ]
    }));
}
<commit_msg>privmsg: text needs `:` prefix<commit_after>use std::io::Write;
use std::io;
use std::str;

use utils::{find_byte};

#[derive(Debug, PartialEq, Eq)]
pub struct Msg {
    pub pfx     : Option<Pfx>,
    pub cmd     : Cmd,
    pub params  : Vec<Vec<u8>>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Pfx {
    Server(String),

    User {
        nick : String,
        /// user@host
        user : String,
    },
}

impl Pfx {
    #[inline]
    pub fn is_server_pfx(&self) -> bool {
        match self {
            &Pfx::Server(_) => true,
            _ => false,
        }
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum Cmd {
    Str(String),
    Num(u16),
}

impl Msg {
    /// Parse a complete IRC message. NOTE: The string should NOT have CR-NL.
    pub fn parse(msg : &[u8]) -> Result<Msg, String> {

        writeln!(&mut io::stderr(), "parsing msg: {:?}", String::from_utf8(msg.to_owned())).unwrap();

        if msg.len() == 0 {
            return Err("Empty msg".to_owned());
        }

        let mut slice = msg;

        let pfx : Option<Pfx> = {
            if msg[0] == b':' {
                // parse prefix
                let ws_idx = find_byte(slice, b' ').unwrap();
                let (mut pfx, slice_) = slice.split_at(ws_idx);
                // drop the : from pfx
                pfx = &pfx[ 1 .. ];
                slice = &slice_[ 1 .. ]; // drop the space
                Some(parse_pfx(&pfx))
            } else {
                // log_stderr_bytes("Can't parse msg prefix:", msg);
                None
            }
        };

        let cmd : Cmd = {
            let ws_idx = find_byte(slice, b' ').unwrap();
            let (cmd, slice_) = slice.split_at(ws_idx);
            slice = &slice_[ 1 .. ]; // drop the space
            match reply_num(cmd) {
                None => Cmd::Str(unsafe {
                    // Cmd strings are added by the server and they're always
                    // ASCII strings, so this is safe and O(1).
                    String::from_utf8_unchecked(cmd.to_owned())
                }),
                Some(num) => Cmd::Num(num)
            }
        };

        let params = try!(parse_params(slice));

        Ok(Msg {
            pfx: pfx,
            cmd: cmd,
            params: params,
        })
    }

    ////////////////////////////////////////////////////////////////////////////
    // Message generation

    pub fn user<W : Write>(hostname : &str, realname : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "USER {} 0 * :{}\r\n", hostname, realname)
    }

    pub fn nick<W : Write>(arg : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "NICK {}\r\n", arg)
    }

    pub fn pong<W : Write>(arg : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "PONG {}\r\n", arg)
    }

    pub fn join<W : Write>(channel : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "JOIN {}\r\n", channel)
    }

    pub fn privmsg<W : Write>(msgtarget : &str, msg : &str, mut sink : W) -> io::Result<()> {
        write!(sink, "PRIVMSG {} :{}\r\n", msgtarget, msg)
    }

    pub fn quit<W : Write>(msg : Option<&str>, mut sink : W) -> io::Result<()> {
        match msg {
            None => write!(sink, "QUIT\r\n"),
            Some(msg) => write!(sink, "QUIT {}\r\n", msg)
        }
    }
}

fn reply_num(bs : &[u8]) -> Option<u16> {
    if bs.len() == 3 {
        let n3 = unsafe { *bs.get_unchecked(0) };
        let n2 = unsafe { *bs.get_unchecked(1) };
        let n1 = unsafe { *bs.get_unchecked(2) };
        if is_num_ascii(n3) && is_num_ascii(n2) && is_num_ascii(n1) {
            return Some(((n3 - b'0') as u16) * 100 +
                        ((n2 - b'0') as u16) * 10  +
                        ((n1 - b'0') as u16));
        }
    }
    None
}

#[inline]
fn is_num_ascii(b : u8) -> bool {
    b >= b'0' && b <= b'9'
}

fn parse_pfx(pfx : &[u8]) -> Pfx {
    match find_byte(pfx, b'!') {
        None => Pfx::Server(unsafe { str::from_utf8_unchecked(pfx).to_owned() }),
        Some(idx) => {
            Pfx::User {
                nick: unsafe { str::from_utf8_unchecked(&pfx[ 0 .. idx ]).to_owned() },
                user: unsafe { str::from_utf8_unchecked(&pfx[ idx + 1 .. ]).to_owned() }
            }
        }
    }
}

fn parse_params(chrs : &[u8]) -> Result<Vec<Vec<u8>>, String> {
    if chrs.len() == 0 {
        return Err("parse_params: Empty slice of chars".to_owned());
    }

    let mut ret : Vec<Vec<u8>> = Vec::new();

    let mut current_param = Vec::new();
    for byte_idx in 0 .. chrs.len() {
        let byte = *unsafe { chrs.get_unchecked(byte_idx) };
        if byte == b':' {
            current_param.extend_from_slice(&chrs[ byte_idx + 1 .. ]);
            ret.push(current_param);
            return Ok(ret);
        } else if byte == b' ' {
            ret.push(current_param);
            current_param = Vec::new();
        } else {
            current_param.push(byte);
        }
    }

    if current_param.len() > 0 {
        ret.push(current_param);
    }

    Ok(ret)
}

////////////////////////////////////////////////////////////////////////////////

#[test]
fn parse_error_1() {
    let msg = b"ERROR :Closing Link: 127.0.0.1 (Client Quit)";
    assert!(Msg::parse(msg).is_ok());
}

#[test]
fn parse_error_2() {
    let msg = b":tiny_test!~tiny@213.153.193.52 JOIN #haskell";
    assert_eq!(Msg::parse(msg), Ok(Msg {
        pfx: Some(Pfx::User {
            nick: "tiny_test".to_string(),
            user: "~tiny@213.153.193.52".to_string(),
        }),
        cmd: Cmd::Str("JOIN".to_string()),
        params: vec![
            (Box::new(*b"#haskell") as Box<[u8]>).into_vec()
        ]
    }));
}

#[test]
fn parse_error_3() {
    let msg = b":verne.freenode.net NOTICE * :*** Couldn\'t look up your hostname";
    assert_eq!(Msg::parse(msg), Ok(Msg {
        pfx: Some(Pfx::Server("verne.freenode.net".to_owned())),
        cmd: Cmd::Str("NOTICE".to_owned()),
        params: vec![
            (Box::new(*b"*") as Box<[u8]>).into_vec(),
            (Box::new(*b"*** Couldn\'t look up your hostname") as Box<[u8]>).into_vec()
        ]
    }));
}
<|endoftext|>


<commit_before>use base::{FromAscii};

trait FromStrHelper: {
    fn signed() -> bool;
}

#[derive(Debug, PartialEq)]
pub enum ParseIntError {
    Empty,
    InvalidDigit,
    Overflow,
    Underflow,
}

#[inline]
pub fn dec_to_digit(c: u8) -> Option<u8> {
    let val = match c {
        b'0' ... b'9' => c - b'0',
        _ => return None,
    };
    Some(val)
}

macro_rules! impl_helpers {
    ($t:ty, $signed: expr) => {
        impl FromStrHelper for $t {
            #[inline]
            fn signed() -> bool { $signed }
        }

        impl FromAscii for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii(src: &[u8]) -> Result<Self, Self::Err> {
                if src.is_empty() {
                    return Err(ParseIntError::Empty);
                }

                let (is_positive, digits) = match src[0] {
                    b'+' => (true, &src[1..]),
                    b'-' if <$t>::signed() => (false, &src[1..]),
                    _ => (true, src)
                };

                if digits.is_empty() {
                    return Err(ParseIntError::Empty);
                }

                let mut result: $t = 0;

                if is_positive {
                    for &c in digits {
                        let x = match dec_to_digit(c) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit),
                        };
                        result = match result.checked_mul(10) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                        result = match result.checked_add(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                    }
                } else {
                    for &c in digits {
                        let x = match dec_to_digit(c) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit),
                        };
                        result = match result.checked_mul(10) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                        result = match result.checked_sub(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                    }
                }
                Ok(result)
            }
        }
    }
}

impl_helpers!(i8, true);
impl_helpers!(i16, true);
impl_helpers!(i32, true);
impl_helpers!(i64, true);
impl_helpers!(isize, true);
impl_helpers!(u8, false);
impl_helpers!(u16, false);
impl_helpers!(u32, false);
impl_helpers!(u64, false);
impl_helpers!(usize, false);

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

}<commit_msg>Rename impl_helpers to implement<commit_after>use base::{FromAscii};

trait FromStrHelper: {
    fn signed() -> bool;
}

#[derive(Debug, PartialEq)]
pub enum ParseIntError {
    Empty,
    InvalidDigit,
    Overflow,
    Underflow,
}

#[inline]
pub fn dec_to_digit(c: u8) -> Option<u8> {
    let val = match c {
        b'0' ... b'9' => c - b'0',
        _ => return None,
    };
    Some(val)
}

macro_rules! implement {
    ($t:ty, $signed: expr) => {
        impl FromStrHelper for $t {
            #[inline]
            fn signed() -> bool { $signed }
        }

        impl FromAscii for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii(src: &[u8]) -> Result<Self, Self::Err> {
                if src.is_empty() {
                    return Err(ParseIntError::Empty);
                }

                let (is_positive, digits) = match src[0] {
                    b'+' => (true, &src[1..]),
                    b'-' if <$t>::signed() => (false, &src[1..]),
                    _ => (true, src)
                };

                if digits.is_empty() {
                    return Err(ParseIntError::Empty);
                }

                let mut result: $t = 0;

                if is_positive {
                    for &c in digits {
                        let x = match dec_to_digit(c) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit),
                        };
                        result = match result.checked_mul(10) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                        result = match result.checked_add(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                    }
                } else {
                    for &c in digits {
                        let x = match dec_to_digit(c) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit),
                        };
                        result = match result.checked_mul(10) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                        result = match result.checked_sub(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                    }
                }
                Ok(result)
            }
        }
    }
}

implement!(i8, true);
implement!(i16, true);
implement!(i32, true);
implement!(i64, true);
implement!(isize, true);
implement!(u8, false);
implement!(u16, false);
implement!(u32, false);
implement!(u64, false);
implement!(usize, false);

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

}<|endoftext|>


<commit_before>// Necessary for using `Mutex<usize>` for conditional variables
#![allow(clippy::mutex_atomic)]

use crate::primitive::sync::{Arc, Condvar, Mutex};
use std::fmt;

/// Enables threads to synchronize the beginning or end of some computation.
///
/// # Wait groups vs barriers
///
/// `WaitGroup` is very similar to [`Barrier`], but there are a few differences:
///
/// * [`Barrier`] needs to know the number of threads at construction, while `WaitGroup` is cloned to
///   register more threads.
///
/// * A [`Barrier`] can be reused even after all threads have synchronized, while a `WaitGroup`
///   synchronizes threads only once.
///
/// * All threads wait for others to reach the [`Barrier`]. With `WaitGroup`, each thread can choose
///   to either wait for other threads or to continue without blocking.
///
/// # Examples
///
/// ```
/// use crossbeam_utils::sync::WaitGroup;
/// use std::thread;
///
/// // Create a new wait group.
/// let wg = WaitGroup::new();
///
/// for _ in 0..4 {
///     // Create another reference to the wait group.
///     let wg = wg.clone();
///
///     thread::spawn(move || {
///         // Do some work.
///
///         // Drop the reference to the wait group.
///         drop(wg);
///     });
/// }
///
/// // Block until all threads have finished their work.
/// wg.wait();
/// ```
///
/// [`Barrier`]: std::sync::Barrier
pub struct WaitGroup {
    inner: Arc<Inner>,
}

/// Inner state of a `WaitGroup`.
struct Inner {
    cvar: Condvar,
    count: Mutex<usize>,
}

impl Default for WaitGroup {
    fn default() -> Self {
        Self {
            inner: Arc::new(Inner {
                cvar: Condvar::new(),
                count: Mutex::new(1),
            }),
        }
    }
}

impl WaitGroup {
    /// Creates a new wait group and returns the single reference to it.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::sync::WaitGroup;
    ///
    /// let wg = WaitGroup::new();
    /// ```
    pub fn new() -> Self {
        Self::default()
    }

    /// Drops this reference and waits until all other references are dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::sync::WaitGroup;
    /// use std::thread;
    ///
    /// let wg = WaitGroup::new();
    ///
    /// thread::spawn({
    ///     let wg = wg.clone();
    ///     move || {
    ///         // Block until both threads have reached `wait()`.
    ///         wg.wait();
    ///     }
    /// });
    ///
    /// // Block until both threads have reached `wait()`.
    /// wg.wait();
    /// ```
    pub fn wait(self) {
        if *self.inner.count.lock().unwrap() == 1 {
            return;
        }

        let inner = self.inner.clone();
        drop(self);

        let mut count = inner.count.lock().unwrap();
        while *count > 0 {
            count = inner.cvar.wait(count).unwrap();
        }
    }
}

impl Drop for WaitGroup {
    fn drop(&mut self) {
        let mut count = self.inner.count.lock().unwrap();
        *count -= 1;

        if *count == 0 {
            self.inner.cvar.notify_all();
        }
    }
}

impl Clone for WaitGroup {
    fn clone(&self) -> WaitGroup {
        let mut count = self.inner.count.lock().unwrap();
        *count += 1;

        WaitGroup {
            inner: self.inner.clone(),
        }
    }
}

impl fmt::Debug for WaitGroup {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let count: &usize = &*self.inner.count.lock().unwrap();
        f.debug_struct("WaitGroup").field("count", count).finish()
    }
}
<commit_msg>Miri: Fix thread leaks in WaitGroup doctest<commit_after>// Necessary for using `Mutex<usize>` for conditional variables
#![allow(clippy::mutex_atomic)]

use crate::primitive::sync::{Arc, Condvar, Mutex};
use std::fmt;

/// Enables threads to synchronize the beginning or end of some computation.
///
/// # Wait groups vs barriers
///
/// `WaitGroup` is very similar to [`Barrier`], but there are a few differences:
///
/// * [`Barrier`] needs to know the number of threads at construction, while `WaitGroup` is cloned to
///   register more threads.
///
/// * A [`Barrier`] can be reused even after all threads have synchronized, while a `WaitGroup`
///   synchronizes threads only once.
///
/// * All threads wait for others to reach the [`Barrier`]. With `WaitGroup`, each thread can choose
///   to either wait for other threads or to continue without blocking.
///
/// # Examples
///
/// ```
/// use crossbeam_utils::sync::WaitGroup;
/// use std::thread;
///
/// // Create a new wait group.
/// let wg = WaitGroup::new();
///
/// for _ in 0..4 {
///     // Create another reference to the wait group.
///     let wg = wg.clone();
///
///     thread::spawn(move || {
///         // Do some work.
///
///         // Drop the reference to the wait group.
///         drop(wg);
///     });
/// }
///
/// // Block until all threads have finished their work.
/// wg.wait();
/// ```
///
/// [`Barrier`]: std::sync::Barrier
pub struct WaitGroup {
    inner: Arc<Inner>,
}

/// Inner state of a `WaitGroup`.
struct Inner {
    cvar: Condvar,
    count: Mutex<usize>,
}

impl Default for WaitGroup {
    fn default() -> Self {
        Self {
            inner: Arc::new(Inner {
                cvar: Condvar::new(),
                count: Mutex::new(1),
            }),
        }
    }
}

impl WaitGroup {
    /// Creates a new wait group and returns the single reference to it.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::sync::WaitGroup;
    ///
    /// let wg = WaitGroup::new();
    /// ```
    pub fn new() -> Self {
        Self::default()
    }

    /// Drops this reference and waits until all other references are dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::sync::WaitGroup;
    /// use std::thread;
    ///
    /// let wg = WaitGroup::new();
    ///
    /// thread::spawn({
    ///     let wg = wg.clone();
    ///     move || {
    ///         // Block until both threads have reached `wait()`.
    ///         wg.wait();
    ///     }
    /// });
    ///
    /// // Block until both threads have reached `wait()`.
    /// wg.wait();
    /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371
    /// ```
    pub fn wait(self) {
        if *self.inner.count.lock().unwrap() == 1 {
            return;
        }

        let inner = self.inner.clone();
        drop(self);

        let mut count = inner.count.lock().unwrap();
        while *count > 0 {
            count = inner.cvar.wait(count).unwrap();
        }
    }
}

impl Drop for WaitGroup {
    fn drop(&mut self) {
        let mut count = self.inner.count.lock().unwrap();
        *count -= 1;

        if *count == 0 {
            self.inner.cvar.notify_all();
        }
    }
}

impl Clone for WaitGroup {
    fn clone(&self) -> WaitGroup {
        let mut count = self.inner.count.lock().unwrap();
        *count += 1;

        WaitGroup {
            inner: self.inner.clone(),
        }
    }
}

impl fmt::Debug for WaitGroup {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let count: &usize = &*self.inner.count.lock().unwrap();
        f.debug_struct("WaitGroup").field("count", count).finish()
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ops::{Sub, Div};
use itertools::Itertools;
use error::*;
use eval::Env;
use types::{Expr, List, Vector, Function, Lambda};
use util::*;

pub fn env<'a>() -> Env<'a> {
    let table: Vec<(&str, Lambda)> = vec![
        ("not", not),
        ("or", or),
        ("and", and),
        ("print", print),
        ("+", add),
        ("-", sub),
        ("*", mul),
        ("/", div),
        ("=", equal),
        ("<", less),
        ("<=", less_eq),
        (">", greater),
        (">=", greater_eq),
        ("first", first),
        ("rest", rest),
        ("cons", cons),
        ("list", list),
        ("exit", exit),
    ];

    let builtins = table
        .into_iter()
        .map(|(symbol, f)| {
            (
                String::from(symbol),
                Expr::from(Function::builtin(symbol, f)),
            )
        })
        .collect::<HashMap<_, _>>();

    Env::new(builtins, None)
}

fn numeric_op<F, G>(name: &str, args: &[Expr], fn_int: F, fn_flt: G) -> Result<Expr>
where
    F: Fn(&[i64]) -> Result<i64>,
    G: Fn(&[f64]) -> Result<f64>,
{
    // Check all arguments are numeric
    if args.iter().all(Expr::is_num) {
        if args.iter().any(Expr::is_flt) {
            // If any are float, promote to float
            let floats = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y as f64,
                    &Expr::Flt(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_flt(&floats).map(Expr::from)
        } else {
            // Otherwise perform integer operation
            let ints = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_int(&ints).map(Expr::from)
        }
    } else {
        Err(format!("#[{}] expected numeric", name).into())
    }
}

pub fn add(args: &[Expr]) -> Result<Expr> {
    numeric_op("+", args,
        |ints| Ok(ints.iter().sum::<i64>()),
        |floats| Ok(floats.iter().sum::<f64>())
    )
}

pub fn sub(args: &[Expr]) -> Result<Expr> {
    ensure_min_args("-", args, 1)?;

    // Check all arguments are numeric
    if !args.iter().all(Expr::is_num) {
        return Err("#[-] expected numeric".into());
    }

    // If one argument, negate and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from(-x)),
            Expr::Flt(x) => Ok(Expr::from(-x)),
            _ => Err("invalid type".into())
        }
    }

    numeric_op("-", args,
        |ints| Ok(ints[1..].iter().fold(ints[0], Sub::sub)),
        |floats| Ok(floats[1..].iter().fold(floats[0], Sub::sub))
    )
}

pub fn mul(args: &[Expr]) -> Result<Expr> {
    numeric_op("*", args,
        |ints| Ok(ints.iter().product::<i64>()),
        |floats| Ok(floats.iter().product::<f64>())
    )
}

pub fn div(args: &[Expr]) -> Result<Expr> {
    ensure_min_args("[/]", args, 1)?;

    // Check all arguments are numeric
    if !args.iter().all(Expr::is_num) {
        return Err("#[-] expected numeric".into());
    }

    // If one argument, invert and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from((x as f64).recip())),
            Expr::Flt(x) => Ok(Expr::from(x.recip())),
            _ => Err("invalid type".into())
        }
    }

    let int_div = |ints: &[i64]| {
        ints[1..].iter()
            .map(|&x| if x == 0i64 { Err("division by zero".into()) } else { Ok(x) })
            .fold_results(ints[0], Div::div)
    };

    numeric_op("/", args,
        int_div,
        |floats| Ok(floats[1..].iter().fold(floats[0], Div::div))
    )
}

pub fn equal(args: &[Expr]) -> Result<Expr> {
    ensure_args("[=]", args, 2)?;
    Ok(Expr::from(args[0] == args[1]))
}

pub fn less(args: &[Expr]) -> Result<Expr> {
    ensure_args("[<]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a < b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn less_eq(args: &[Expr]) -> Result<Expr> {
    ensure_args("[<=]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a <= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater(args: &[Expr]) -> Result<Expr> {
    ensure_args("[>]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a > b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater_eq(args: &[Expr]) -> Result<Expr> {
    ensure_args("[>=]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a >= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn not(args: &[Expr]) -> Result<Expr> {
    ensure_args("[not]", args, 1)?;
    Ok(Expr::from(!args[0].truthiness()))
}

// TODO: convert to special form
pub fn and(args: &[Expr]) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[and] expected boolean argument".into())
        .map(|bools| bools.iter().all(|b| *b))
        .map(Expr::from)
}

// TODO: convert to special form
pub fn or(args: &[Expr]) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[or] expected boolean argument".into())
        .map(|bools| bools.iter().any(|b| *b))
        .map(Expr::from)
}

pub fn print(args: &[Expr]) -> Result<Expr> {
    ensure_args("#[print]", args, 1)?;
    println!("{}", args[0]);
    Ok(Expr::Nil)
}

pub fn first(args: &[Expr]) -> Result<Expr> {
    ensure_args("#[first]", args, 1)?;

    match &args[0] {
        &Expr::List(ref l) => Ok(l.0.first().cloned().unwrap_or(Expr::Nil)),
        &Expr::Vector(ref q) => Ok(q.0.first().cloned().unwrap_or(Expr::Nil)),
        _ => Err("#[first] expected list".into()),
    }
}

pub fn rest(args: &[Expr]) -> Result<Expr> {
    match &args[0] {
        &Expr::List(ref l) => {
            Ok(
                l.0
                    .split_first()
                    .map(|(_, rest)| Expr::List(List(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        &Expr::Vector(ref v) => {
            Ok(
                v.0
                    .split_first()
                    .map(|(_, rest)| Expr::Vector(Vector(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        _ => Err("#[rest] expected list".into()),
    }
}

// (cons item seq)
pub fn cons(args: &[Expr]) -> Result<Expr> {
    ensure_args("cons]", args, 2)?;

    match &args[2] {
        &Expr::List(ref l) => {
            let mut new = l.clone();
            new.0.insert(0, args[1].clone());
            Ok(Expr::List(new))
        }
        &Expr::Vector(ref v) => {
            let mut new = v.clone();
            new.0.push(args[1].clone());
            Ok(Expr::Vector(new))
        }
        _ => Err("#[cons] expected list".into()),
    }
}

// (list items*)
pub fn list(args: &[Expr]) -> Result<Expr> {
    if args.is_empty() {
        Ok(Expr::Nil)
    } else {
        Ok(Expr::List(List(args.to_vec())))
    }
}

// (exit)
pub fn exit(_args: &[Expr]) -> Result<Expr> {
    Err(ErrorKind::Exit(0).into())
}
<commit_msg>Ops error cleanup<commit_after>use std::collections::HashMap;
use std::ops::{Sub, Div};
use itertools::Itertools;
use error::*;
use eval::Env;
use types::{Expr, List, Vector, Function, Lambda};
use util::*;

pub fn env<'a>() -> Env<'a> {
    let table: Vec<(&str, Lambda)> = vec![
        ("not", not),
        ("or", or),
        ("and", and),
        ("print", print),
        ("+", add),
        ("-", sub),
        ("*", mul),
        ("/", div),
        ("=", equal),
        ("<", less),
        ("<=", less_eq),
        (">", greater),
        (">=", greater_eq),
        ("first", first),
        ("rest", rest),
        ("cons", cons),
        ("list", list),
        ("exit", exit),
    ];

    let builtins = table
        .into_iter()
        .map(|(symbol, f)| {
            (
                String::from(symbol),
                Expr::from(Function::builtin(symbol, f)),
            )
        })
        .collect::<HashMap<_, _>>();

    Env::new(builtins, None)
}

fn numeric_op<F, G>(name: &str, args: &[Expr], fn_int: F, fn_flt: G) -> Result<Expr>
where
    F: Fn(&[i64]) -> Result<i64>,
    G: Fn(&[f64]) -> Result<f64>,
{
    // Check all arguments are numeric
    if args.iter().all(Expr::is_num) {
        if args.iter().any(Expr::is_flt) {
            // If any are float, promote to float
            let floats = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y as f64,
                    &Expr::Flt(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_flt(&floats).map(Expr::from)
        } else {
            // Otherwise perform integer operation
            let ints = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_int(&ints).map(Expr::from)
        }
    } else {
        Err(format!("#[{}] expected numeric", name).into())
    }
}

pub fn add(args: &[Expr]) -> Result<Expr> {
    numeric_op("+", args,
        |ints| Ok(ints.iter().sum::<i64>()),
        |floats| Ok(floats.iter().sum::<f64>())
    )
}

pub fn sub(args: &[Expr]) -> Result<Expr> {
    ensure_min_args("-", args, 1)?;

    // If one argument, negate and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from(-x)),
            Expr::Flt(x) => Ok(Expr::from(-x)),
            _ => Err("invalid type".into())
        }
    }

    numeric_op("-", args,
        |ints| Ok(ints[1..].iter().fold(ints[0], Sub::sub)),
        |floats| Ok(floats[1..].iter().fold(floats[0], Sub::sub))
    )
}

pub fn mul(args: &[Expr]) -> Result<Expr> {
    numeric_op("*", args,
        |ints| Ok(ints.iter().product::<i64>()),
        |floats| Ok(floats.iter().product::<f64>())
    )
}

pub fn div(args: &[Expr]) -> Result<Expr> {
    ensure_min_args("/", args, 1)?;

    // If one argument, invert and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from((x as f64).recip())),
            Expr::Flt(x) => Ok(Expr::from(x.recip())),
            _ => Err("invalid type".into())
        }
    }

    let int_div = |ints: &[i64]| {
        ints[1..].iter()
            .map(|&x| if x == 0i64 { Err("division by zero".into()) } else { Ok(x) })
            .fold_results(ints[0], Div::div)
    };

    numeric_op("/", args,
        int_div,
        |floats| Ok(floats[1..].iter().fold(floats[0], Div::div))
    )
}

pub fn equal(args: &[Expr]) -> Result<Expr> {
    ensure_args("=", args, 2)?;
    Ok(Expr::from(args[0] == args[1]))
}

pub fn less(args: &[Expr]) -> Result<Expr> {
    ensure_args("<", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a < b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn less_eq(args: &[Expr]) -> Result<Expr> {
    ensure_args("<=", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a <= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater(args: &[Expr]) -> Result<Expr> {
    ensure_args(">", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a > b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater_eq(args: &[Expr]) -> Result<Expr> {
    ensure_args(">=", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a >= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn not(args: &[Expr]) -> Result<Expr> {
    ensure_args("[not]", args, 1)?;
    Ok(Expr::from(!args[0].truthiness()))
}

// TODO: convert to special form
pub fn and(args: &[Expr]) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[and] expected boolean argument".into())
        .map(|bools| bools.iter().all(|b| *b))
        .map(Expr::from)
}

// TODO: convert to special form
pub fn or(args: &[Expr]) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[or] expected boolean argument".into())
        .map(|bools| bools.iter().any(|b| *b))
        .map(Expr::from)
}

// (print expr)
pub fn print(args: &[Expr]) -> Result<Expr> {
    ensure_args("print", args, 1)?;
    println!("{}", args[0]);
    Ok(Expr::Nil)
}

// (first seq)
pub fn first(args: &[Expr]) -> Result<Expr> {
    ensure_args("first", args, 1)?;

    match &args[0] {
        &Expr::List(ref l) => Ok(l.0.first().cloned().unwrap_or(Expr::Nil)),
        &Expr::Vector(ref q) => Ok(q.0.first().cloned().unwrap_or(Expr::Nil)),
        _ => Err("#[first] expected list".into()),
    }
}

// (rest seq)
pub fn rest(args: &[Expr]) -> Result<Expr> {
    ensure_args("first", args, 1)?;
    match &args[0] {
        &Expr::List(ref l) => {
            Ok(
                l.0
                    .split_first()
                    .map(|(_, rest)| Expr::List(List(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        &Expr::Vector(ref v) => {
            Ok(
                v.0
                    .split_first()
                    .map(|(_, rest)| Expr::Vector(Vector(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        _ => Err("#[rest] expected list".into()),
    }
}

// (cons item seq)
pub fn cons(args: &[Expr]) -> Result<Expr> {
    ensure_args("cons", args, 2)?;

    match &args[2] {
        &Expr::List(ref l) => {
            let mut new = l.clone();
            new.0.insert(0, args[1].clone());
            Ok(Expr::List(new))
        }
        &Expr::Vector(ref v) => {
            let mut new = v.clone();
            new.0.push(args[1].clone());
            Ok(Expr::Vector(new))
        }
        _ => Err("#[cons] expected list".into()),
    }
}

// (list items*)
pub fn list(args: &[Expr]) -> Result<Expr> {
    if args.is_empty() {
        Ok(Expr::Nil)
    } else {
        Ok(Expr::List(List(args.to_vec())))
    }
}

// (exit)
pub fn exit(_args: &[Expr]) -> Result<Expr> {
    Err(ErrorKind::Exit(0).into())
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

extern crate cgmath;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate time;
extern crate rand;
extern crate genmesh;
extern crate noise;

use rand::Rng;
use cgmath::FixedArray;
use cgmath::{Matrix4, Point3, Vector3};
use cgmath::{Transform, AffineMatrix3};
use gfx::mesh::ToIndexSlice;
use gfx::traits::{Stream, FactoryExt};
use genmesh::{Vertices, Triangulate};
use genmesh::generators::{Plane, SharedVertex, IndexedPolygon};
use time::precise_time_s;

use noise::{Seed, perlin2};

gfx_vertex!( Vertex {
    a_Pos@ pos: [f32; 3],
    a_Color@ color: [f32; 3],
});

gfx_parameters!( Params {
    u_Model@ model: [[f32; 4]; 4],
    u_View@ view: [[f32; 4]; 4],
    u_Proj@ proj: [[f32; 4]; 4],
});

fn calculate_color(height: f32) -> [f32; 3] {
    if height > 8.0 {
        [0.9, 0.9, 0.9] // white
    } else if height > 0.0 {
        [0.7, 0.7, 0.7] // greay
    } else if height > -5.0 {
        [0.2, 0.7, 0.2] // green
    } else {
        [0.2, 0.2, 0.7] // blue
    }
}

pub fn main() {
    let (mut stream, mut device, mut factory) = gfx_window_glutin::init(
        glutin::Window::new().unwrap());
    stream.out.window.set_title("Terrain example");

    let rand_seed = rand::thread_rng().gen();
    let seed = Seed::new(rand_seed);
    let plane = Plane::subdivide(256, 256);
    let vertex_data: Vec<Vertex> = plane.shared_vertex_iter()
        .map(|(x, y)| {
            let h = perlin2(&seed, &[x, y]) * 32.0;
            Vertex {
                pos: [25.0 * x, 25.0 * y, h],
                color: calculate_color(h),
            }
        })
        .collect();

    let index_data: Vec<u32> = plane.indexed_polygon_iter()
        .triangulate()
        .vertices()
        .map(|i| i as u32)
        .collect();
    let slice = index_data.to_slice(&mut factory);
    let mesh = factory.create_mesh(&vertex_data);
    let program = {
        let vs = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("terrain_120.glslv")),
            glsl_150: Some(include_bytes!("terrain_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fs = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("terrain_120.glslf")),
            glsl_150: Some(include_bytes!("terrain_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vs, fs).unwrap()
    };

    let data = Params {
        model: Matrix4::identity().into_fixed(),
        view: Matrix4::identity().into_fixed(),
        proj: cgmath::perspective(cgmath::deg(60.0f32),
                                  stream.get_aspect_ratio(),
                                  0.1, 1000.0
                                  ).into_fixed(),
        _r: std::marker::PhantomData,
    };
    let mut batch = gfx::batch::Full::new(mesh, program, data)
                                     .unwrap();
    batch.slice = slice;
    batch.state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    'main: loop {
        // quit when Esc is pressed.
        for event in stream.out.window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) => break 'main,
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        let time = precise_time_s() as f32;
        let x = time.sin();
        let y = time.cos();
        let view: AffineMatrix3<f32> = Transform::look_at(
            &Point3::new(x * 32.0, y * 32.0, 16.0),
            &Point3::new(0.0, 0.0, 0.0),
            &Vector3::unit_z(),
        );
        batch.params.view = view.mat.into_fixed();

        stream.clear(gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        });
        stream.draw(&batch).unwrap();
        stream.present(&mut device);
    }
}
<commit_msg>PSO - ported the terrain example<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

extern crate cgmath;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate time;
extern crate rand;
extern crate genmesh;
extern crate noise;

use rand::Rng;
use cgmath::FixedArray;
use cgmath::{Matrix4, Point3, Vector3};
use cgmath::{Transform, AffineMatrix3};
use gfx::format::{DepthStencil, Rgba8};
use genmesh::{Vertices, Triangulate};
use genmesh::generators::{Plane, SharedVertex, IndexedPolygon};
use time::precise_time_s;
use noise::{Seed, perlin2};

gfx_vertex_struct!( Vertex {
    pos: [f32; 3] = "a_Pos",
    color: [f32; 3] = "a_Color",
});

gfx_pipeline_init!( PipeData PipeMeta PipeInit {
    vbuf: gfx::VertexBuffer<Vertex> = gfx::PER_VERTEX,
    model: gfx::Global<[[f32; 4]; 4]> = "u_Model",
    view: gfx::Global<[[f32; 4]; 4]> = "u_View",
    proj: gfx::Global<[[f32; 4]; 4]> = "u_Proj",
    out_color: gfx::RenderTarget<Rgba8> = ("o_Color", gfx::state::MASK_ALL),
    out_depth: gfx::DepthTarget<DepthStencil> = gfx::state::Depth {
        fun: gfx::state::Comparison::LessEqual,
        write: true,
    },
});

fn calculate_color(height: f32) -> [f32; 3] {
    if height > 8.0 {
        [0.9, 0.9, 0.9] // white
    } else if height > 0.0 {
        [0.7, 0.7, 0.7] // greay
    } else if height > -5.0 {
        [0.2, 0.7, 0.2] // green
    } else {
        [0.2, 0.2, 0.7] // blue
    }
}

pub fn main() {
    use gfx::traits::{Device, FactoryExt};

    let builder = glutin::WindowBuilder::new()
        .with_title("Terrain example".to_string());
    let (window, mut device, mut factory, main_color, main_depth) =
        gfx_window_glutin::init_new::<gfx::format::Rgba8>(builder);
    let mut encoder = factory.create_encoder();

    let rand_seed = rand::thread_rng().gen();
    let seed = Seed::new(rand_seed);
    let plane = Plane::subdivide(256, 256);
    let vertex_data: Vec<Vertex> = plane.shared_vertex_iter()
        .map(|(x, y)| {
            let h = perlin2(&seed, &[x, y]) * 32.0;
            Vertex {
                pos: [25.0 * x, 25.0 * y, h],
                color: calculate_color(h),
            }
        })
        .collect();

    let index_data: Vec<u32> = plane.indexed_polygon_iter()
        .triangulate()
        .vertices()
        .map(|i| i as u32)
        .collect();

    let (vbuf, slice) = factory.create_vertex_buffer_indexed(&vertex_data, &index_data[..]);

    let shaders = factory.create_shader_set(
        include_bytes!("terrain_150.glslv"),
        include_bytes!("terrain_150.glslf")
        ).unwrap();

    let pso = factory.create_pipeline_state(&shaders,
        gfx::Primitive::TriangleList,
        gfx::state::Rasterizer::new_fill(gfx::state::CullFace::Back),
        &PipeInit::new()
        ).unwrap();

    let aspect_ratio = {
        let (w, h) = window.get_inner_size().unwrap();
        w as f32 / h as f32
    };

    let mut data = PipeData {
        vbuf: vbuf,
        model: Matrix4::identity().into_fixed(),
        view: Matrix4::identity().into_fixed(),
        proj: cgmath::perspective(
            cgmath::deg(60.0f32), aspect_ratio, 0.1, 1000.0
            ).into_fixed(),
        out_color: main_color,
        out_depth: main_depth,
    };

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        let time = precise_time_s() as f32;
        let x = time.sin();
        let y = time.cos();
        let view: AffineMatrix3<f32> = Transform::look_at(
            &Point3::new(x * 32.0, y * 32.0, 16.0),
            &Point3::new(0.0, 0.0, 0.0),
            &Vector3::unit_z(),
        );

        encoder.reset();
        encoder.clear_target(&data.out_color, [0.3, 0.3, 0.3, 1.0]);
        encoder.clear_depth(&data.out_depth, 1.0);

        data.view = view.mat.into_fixed();
        encoder.draw_pipeline(&slice, &pso, &data);

        device.submit(encoder.as_buffer());
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<|endoftext|>


<commit_before>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        raw_todo: ~str
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", priority: '^'};

        task.todo = todo.clone();

        return task;
}

fn main () {

        let t = create_task(~"some important task", 1);
}
<commit_msg>making sure we are well initiated<commit_after>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", priority: '^',
                                contexts: &[], projects: &[]};

        task.todo = todo.clone();

        return task;
}

fn main () {

        let t = create_task(~"some important task", 1);
}
<|endoftext|>


<commit_before>use crate::reflect::message::message_ref::MessageRef;
use crate::reflect::value::value_ref::ReflectValueMut;
use crate::reflect::value::value_ref::ReflectValueRef;
use crate::reflect::EnumDescriptor;
use crate::reflect::EnumValueDescriptor;
use crate::reflect::ProtobufValueSized;
use crate::reflect::RuntimeTypeBox;
use crate::MessageDyn;
use std::hash::Hash;
use std::hash::Hasher;

/// Owner value of any elementary type
#[derive(Debug, Clone)]
pub enum ReflectValueBox {
    /// `u32`
    U32(u32),
    /// `u64`
    U64(u64),
    /// `i32`
    I32(i32),
    /// `i64`
    I64(i64),
    /// `f32`
    F32(f32),
    /// `f64`
    F64(f64),
    /// `bool`
    Bool(bool),
    /// `string`
    String(String),
    /// `bytes`
    Bytes(Vec<u8>),
    /// `enum`
    Enum(EnumDescriptor, i32),
    /// `message`
    Message(Box<dyn MessageDyn>),
}

impl From<u32> for ReflectValueBox {
    fn from(v: u32) -> Self {
        ReflectValueBox::U32(v)
    }
}

impl From<u64> for ReflectValueBox {
    fn from(v: u64) -> Self {
        ReflectValueBox::U64(v)
    }
}

impl From<i32> for ReflectValueBox {
    fn from(v: i32) -> Self {
        ReflectValueBox::I32(v)
    }
}

impl From<i64> for ReflectValueBox {
    fn from(v: i64) -> Self {
        ReflectValueBox::I64(v)
    }
}

impl From<f32> for ReflectValueBox {
    fn from(v: f32) -> Self {
        ReflectValueBox::F32(v)
    }
}

impl From<f64> for ReflectValueBox {
    fn from(v: f64) -> Self {
        ReflectValueBox::F64(v)
    }
}

impl From<bool> for ReflectValueBox {
    fn from(v: bool) -> Self {
        ReflectValueBox::Bool(v)
    }
}

impl From<String> for ReflectValueBox {
    fn from(v: String) -> Self {
        ReflectValueBox::String(v)
    }
}

impl From<Vec<u8>> for ReflectValueBox {
    fn from(v: Vec<u8>) -> Self {
        ReflectValueBox::Bytes(v)
    }
}

impl<'a> From<&'a EnumValueDescriptor> for ReflectValueBox {
    fn from(v: &'a EnumValueDescriptor) -> Self {
        ReflectValueBox::from(v.clone())
    }
}

impl From<EnumValueDescriptor> for ReflectValueBox {
    fn from(v: EnumValueDescriptor) -> Self {
        let number = v.value();
        ReflectValueBox::Enum(v.enum_descriptor, number)
    }
}

impl From<Box<dyn MessageDyn>> for ReflectValueBox {
    fn from(v: Box<dyn MessageDyn>) -> Self {
        ReflectValueBox::Message(v)
    }
}

fn _assert_value_box_send_sync() {
    fn _assert_send_sync<T: Send + Sync>() {}
    _assert_send_sync::<ReflectValueBox>();
}

impl ReflectValueBox {
    /// Type of this value.
    pub fn get_type(&self) -> RuntimeTypeBox {
        self.as_value_ref().get_type()
    }

    /// As ref
    pub fn as_value_ref(&self) -> ReflectValueRef {
        match self {
            ReflectValueBox::U32(v) => ReflectValueRef::U32(*v),
            ReflectValueBox::U64(v) => ReflectValueRef::U64(*v),
            ReflectValueBox::I32(v) => ReflectValueRef::I32(*v),
            ReflectValueBox::I64(v) => ReflectValueRef::I64(*v),
            ReflectValueBox::F32(v) => ReflectValueRef::F32(*v),
            ReflectValueBox::F64(v) => ReflectValueRef::F64(*v),
            ReflectValueBox::Bool(v) => ReflectValueRef::Bool(*v),
            ReflectValueBox::String(ref v) => ReflectValueRef::String(v.as_str()),
            ReflectValueBox::Bytes(ref v) => ReflectValueRef::Bytes(v.as_slice()),
            ReflectValueBox::Enum(d, v) => ReflectValueRef::Enum(d.clone(), *v),
            ReflectValueBox::Message(v) => ReflectValueRef::Message(MessageRef::from(&**v)),
        }
    }

    pub(crate) fn as_value_mut(&mut self) -> ReflectValueMut {
        match self {
            ReflectValueBox::Message(m) => ReflectValueMut::Message(&mut **m),
            _ => panic!(
                "ReflectValueMut cannot be constructed from {:?}",
                self.get_type()
            ),
        }
    }

    /// Downcast to real typed value.
    ///
    /// For `enum` `V` can be either `V: ProtobufEnum` or `V: ProtobufEnumOrUnknown<E>`.
    pub fn downcast<V: ProtobufValueSized>(self) -> Result<V, Self> {
        V::from_value_box(self)
    }
}

impl<'a> PartialEq for ReflectValueBox {
    fn eq(&self, other: &Self) -> bool {
        self.as_value_ref() == other.as_value_ref()
    }
}

impl<'a> PartialEq<ReflectValueBox> for ReflectValueRef<'a> {
    fn eq(&self, other: &ReflectValueBox) -> bool {
        *self == other.as_value_ref()
    }
}

// Panics if contained type is not hashable
impl Hash for ReflectValueBox {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&self.as_value_ref(), state)
    }
}

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

    #[test]
    fn reflect_value_box_downcast_primitive() {
        assert_eq!(Ok(10), ReflectValueBox::U32(10).downcast::<u32>());
        assert_eq!(
            Err(ReflectValueBox::I32(10)),
            ReflectValueBox::I32(10).downcast::<u32>()
        );
    }

    #[test]
    fn reflect_value_box_downcast_string() {
        assert_eq!(
            Ok("aa".to_owned()),
            ReflectValueBox::String("aa".to_owned()).downcast::<String>()
        );
        assert_eq!(
            Err(ReflectValueBox::String("aa".to_owned())),
            ReflectValueBox::String("aa".to_owned()).downcast::<u32>()
        );
        assert_eq!(
            Err(ReflectValueBox::Bool(false)),
            ReflectValueBox::Bool(false).downcast::<String>()
        );
    }
}
<commit_msg>Hash is no longer needed for ReflectValueBox<commit_after>use crate::reflect::message::message_ref::MessageRef;
use crate::reflect::value::value_ref::ReflectValueMut;
use crate::reflect::value::value_ref::ReflectValueRef;
use crate::reflect::EnumDescriptor;
use crate::reflect::EnumValueDescriptor;
use crate::reflect::ProtobufValueSized;
use crate::reflect::RuntimeTypeBox;
use crate::MessageDyn;

/// Owner value of any elementary type
#[derive(Debug, Clone)]
pub enum ReflectValueBox {
    /// `u32`
    U32(u32),
    /// `u64`
    U64(u64),
    /// `i32`
    I32(i32),
    /// `i64`
    I64(i64),
    /// `f32`
    F32(f32),
    /// `f64`
    F64(f64),
    /// `bool`
    Bool(bool),
    /// `string`
    String(String),
    /// `bytes`
    Bytes(Vec<u8>),
    /// `enum`
    Enum(EnumDescriptor, i32),
    /// `message`
    Message(Box<dyn MessageDyn>),
}

impl From<u32> for ReflectValueBox {
    fn from(v: u32) -> Self {
        ReflectValueBox::U32(v)
    }
}

impl From<u64> for ReflectValueBox {
    fn from(v: u64) -> Self {
        ReflectValueBox::U64(v)
    }
}

impl From<i32> for ReflectValueBox {
    fn from(v: i32) -> Self {
        ReflectValueBox::I32(v)
    }
}

impl From<i64> for ReflectValueBox {
    fn from(v: i64) -> Self {
        ReflectValueBox::I64(v)
    }
}

impl From<f32> for ReflectValueBox {
    fn from(v: f32) -> Self {
        ReflectValueBox::F32(v)
    }
}

impl From<f64> for ReflectValueBox {
    fn from(v: f64) -> Self {
        ReflectValueBox::F64(v)
    }
}

impl From<bool> for ReflectValueBox {
    fn from(v: bool) -> Self {
        ReflectValueBox::Bool(v)
    }
}

impl From<String> for ReflectValueBox {
    fn from(v: String) -> Self {
        ReflectValueBox::String(v)
    }
}

impl From<Vec<u8>> for ReflectValueBox {
    fn from(v: Vec<u8>) -> Self {
        ReflectValueBox::Bytes(v)
    }
}

impl<'a> From<&'a EnumValueDescriptor> for ReflectValueBox {
    fn from(v: &'a EnumValueDescriptor) -> Self {
        ReflectValueBox::from(v.clone())
    }
}

impl From<EnumValueDescriptor> for ReflectValueBox {
    fn from(v: EnumValueDescriptor) -> Self {
        let number = v.value();
        ReflectValueBox::Enum(v.enum_descriptor, number)
    }
}

impl From<Box<dyn MessageDyn>> for ReflectValueBox {
    fn from(v: Box<dyn MessageDyn>) -> Self {
        ReflectValueBox::Message(v)
    }
}

fn _assert_value_box_send_sync() {
    fn _assert_send_sync<T: Send + Sync>() {}
    _assert_send_sync::<ReflectValueBox>();
}

impl ReflectValueBox {
    /// Type of this value.
    pub fn get_type(&self) -> RuntimeTypeBox {
        self.as_value_ref().get_type()
    }

    /// As ref
    pub fn as_value_ref(&self) -> ReflectValueRef {
        match self {
            ReflectValueBox::U32(v) => ReflectValueRef::U32(*v),
            ReflectValueBox::U64(v) => ReflectValueRef::U64(*v),
            ReflectValueBox::I32(v) => ReflectValueRef::I32(*v),
            ReflectValueBox::I64(v) => ReflectValueRef::I64(*v),
            ReflectValueBox::F32(v) => ReflectValueRef::F32(*v),
            ReflectValueBox::F64(v) => ReflectValueRef::F64(*v),
            ReflectValueBox::Bool(v) => ReflectValueRef::Bool(*v),
            ReflectValueBox::String(ref v) => ReflectValueRef::String(v.as_str()),
            ReflectValueBox::Bytes(ref v) => ReflectValueRef::Bytes(v.as_slice()),
            ReflectValueBox::Enum(d, v) => ReflectValueRef::Enum(d.clone(), *v),
            ReflectValueBox::Message(v) => ReflectValueRef::Message(MessageRef::from(&**v)),
        }
    }

    pub(crate) fn as_value_mut(&mut self) -> ReflectValueMut {
        match self {
            ReflectValueBox::Message(m) => ReflectValueMut::Message(&mut **m),
            _ => panic!(
                "ReflectValueMut cannot be constructed from {:?}",
                self.get_type()
            ),
        }
    }

    /// Downcast to real typed value.
    ///
    /// For `enum` `V` can be either `V: ProtobufEnum` or `V: ProtobufEnumOrUnknown<E>`.
    pub fn downcast<V: ProtobufValueSized>(self) -> Result<V, Self> {
        V::from_value_box(self)
    }
}

impl<'a> PartialEq for ReflectValueBox {
    fn eq(&self, other: &Self) -> bool {
        self.as_value_ref() == other.as_value_ref()
    }
}

impl<'a> PartialEq<ReflectValueBox> for ReflectValueRef<'a> {
    fn eq(&self, other: &ReflectValueBox) -> bool {
        *self == other.as_value_ref()
    }
}

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

    #[test]
    fn reflect_value_box_downcast_primitive() {
        assert_eq!(Ok(10), ReflectValueBox::U32(10).downcast::<u32>());
        assert_eq!(
            Err(ReflectValueBox::I32(10)),
            ReflectValueBox::I32(10).downcast::<u32>()
        );
    }

    #[test]
    fn reflect_value_box_downcast_string() {
        assert_eq!(
            Ok("aa".to_owned()),
            ReflectValueBox::String("aa".to_owned()).downcast::<String>()
        );
        assert_eq!(
            Err(ReflectValueBox::String("aa".to_owned())),
            ReflectValueBox::String("aa".to_owned()).downcast::<u32>()
        );
        assert_eq!(
            Err(ReflectValueBox::Bool(false)),
            ReflectValueBox::Bool(false).downcast::<String>()
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![no_main]

use std::convert::TryInto;

use cros_fuzz::fuzz_target;
use devices::virtio::fs::fuzzing::fuzz_server;
use devices::virtio::{create_descriptor_chain, DescriptorType, Reader, Writer};
use vm_memory::{GuestAddress, GuestMemory};

const MEM_SIZE: u64 = 256 * 1024 * 1024;
const BUFFER_ADDR: GuestAddress = GuestAddress(0x100);

thread_local! {
    static GUEST_MEM: GuestMemory = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
}

fuzz_target!(|data| {
    use DescriptorType::*;

    GUEST_MEM.with(|mem| {
        mem.write_all_at_addr(data, BUFFER_ADDR).unwrap();

        let chain = create_descriptor_chain(
            mem,
            GuestAddress(0),
            BUFFER_ADDR,
            vec![
                (Readable, data.len().try_into().unwrap()),
                (
                    Writable,
                    (MEM_SIZE as u32)
                        .saturating_sub(data.len().try_into().unwrap())
                        .saturating_sub(0x100),
                ),
            ],
            0,
        )
        .unwrap();

        let r = Reader::new(mem, chain.clone()).unwrap();
        let w = Writer::new(mem, chain).unwrap();
        fuzz_server(r, w);
    });
});
<commit_msg>fuzz: fix build<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![no_main]

use std::convert::TryInto;

use cros_fuzz::fuzz_target;
use devices::virtio::fs::fuzzing::fuzz_server;
use devices::virtio::{create_descriptor_chain, DescriptorType, Reader, Writer};
use vm_memory::{GuestAddress, GuestMemory};

const MEM_SIZE: u64 = 256 * 1024 * 1024;
const BUFFER_ADDR: GuestAddress = GuestAddress(0x100);

thread_local! {
    static GUEST_MEM: GuestMemory = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
}

fuzz_target!(|data| {
    use DescriptorType::*;

    GUEST_MEM.with(|mem| {
        mem.write_all_at_addr(data, BUFFER_ADDR).unwrap();

        let chain = create_descriptor_chain(
            mem,
            GuestAddress(0),
            BUFFER_ADDR,
            vec![
                (Readable, data.len().try_into().unwrap()),
                (
                    Writable,
                    (MEM_SIZE as u32)
                        .saturating_sub(data.len().try_into().unwrap())
                        .saturating_sub(0x100),
                ),
            ],
            0,
        )
        .unwrap();

        let r = Reader::new(mem.clone(), chain.clone()).unwrap();
        let w = Writer::new(mem.clone(), chain).unwrap();
        fuzz_server(r, w);
    });
});
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;

use context;
use dispatcher::request::{InternalRequest, Request, RequestHandler};
use dispatcher::response::ResponseHandler;
use dispatcher::Response;
use context::event::EventHandler;
use message::{Message, PatternId};
use reactor;

pub struct MessageEventHandler {
    handlers: HashMap<PatternId, Vec<Rc<RefCell<Box<context::event::EventHandler<InternalRequest>>>>>>,
    keyless_handlers: Vec<Rc<RefCell<Box<context::event::EventHandler<InternalRequest>>>>>,
    response_handler: Rc<RefCell<Box<ResponseHandler<Response>>>>,
}

impl MessageEventHandler {
    pub fn new(response_handler: Rc<RefCell<Box<ResponseHandler<Response>>>>) -> MessageEventHandler {
        MessageEventHandler{
            handlers: HashMap::new(),
            keyless_handlers: Vec::new(),
            response_handler: response_handler
        }
    }

    pub fn register_handler(&mut self, handler: Rc<RefCell<Box<context::event::EventHandler<InternalRequest>>>>) {
        let cloned_handler = handler.clone();
        if handler.borrow().handlers().is_empty() {
            self.keyless_handlers.push(cloned_handler);
        } else {
            for key in cloned_handler.borrow().handlers() {
                println!("key: {:?}", key);
                let handlers = self.handlers.entry(key.clone()).or_insert(Vec::new());
                handlers.push(cloned_handler.clone());
            }
        }
    }

    pub fn call_handlers_by_id(&mut self, id: &PatternId, event: Rc<Message>) {
        if let Some(handlers) = self.handlers.get_mut(id) {
            for i in handlers.iter_mut() {
                if let Some(result) = i.borrow_mut().handle_event(Request::Message(event.clone())) {
                    for i in result.into_iter() {
                        self.response_handler.borrow_mut().handle_response(i.into());
                    }
                }
            }
        } else {
            println!("no handler found for id: {:?}", id);
        }
    }
}

impl reactor::EventHandler<InternalRequest> for MessageEventHandler {
    type Handler = RequestHandler;
    fn handle_event(&mut self, event: InternalRequest) {
        if let Request::Message(event) = event {
            println!("message event");
            if let Some(id) = event.name() {
                self.call_handlers_by_id(id, event.clone());
            } else {
                let id = event.uuid();
                self.call_handlers_by_id(id, event.clone());
            }

            for i in self.keyless_handlers.iter_mut() {
                i.borrow_mut().handle_event(Request::Message(event.clone()));
            }
        } else {
            unreachable!("MessageEventHandler should only handle Message events");
        }
    }
    fn handler(&self) -> Self::Handler {
        RequestHandler::Message
    }
}

#[cfg(test)]
mod test {
    use uuid::Uuid;
    use std::cell::RefCell;
    use std::rc::Rc;

    use action::ExecResult;
    use context;
    use dispatcher::request::{InternalRequest, Request};
    use dispatcher::response::ResponseHandler;
    use dispatcher::Response;
    use message::{Builder, PatternId};
    use reactor::EventHandler;

    use super::MessageEventHandler;

    struct DummyResponseHandler(Rc<RefCell<i32>>);

    impl ResponseHandler<Response> for DummyResponseHandler {
        fn handle_response(&mut self, _: Response) {
            *self.0.borrow_mut() += 1;
        }
    }

    struct DummyEventHandler {
        counter: Rc<RefCell<i32>>,
        ids: Vec<PatternId>
    }

    impl context::event::EventHandler<InternalRequest> for DummyEventHandler {
        fn handle_event(&mut self, _: InternalRequest) -> Option<Vec<ExecResult>> {
            *self.counter.borrow_mut() += 1;
            None
        }
        fn handlers(&self) -> &[PatternId] {
            &self.ids
        }
    }

    #[test]
    fn test_given_message_event_handler_when_it_receives_a_message_then_it_calls_the_right_handler() {
        let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
        let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
        let response_handler_counter = Rc::new(RefCell::new(0));
        let response_handler: Box<ResponseHandler<Response>> = Box::new(DummyResponseHandler(response_handler_counter.clone()));
        let response_handler = Rc::new(RefCell::new(response_handler));
        let ids_1 = vec![ PatternId::Uuid(Uuid::parse_str(&uuid1).unwrap()) ];
        let ids_2 = vec![ PatternId::Uuid(Uuid::parse_str(&uuid2).unwrap()) ];
        let event_handler_counter_1 = Rc::new(RefCell::new(0));
        let event_handler_counter_2 = Rc::new(RefCell::new(0));
        let event_handler_1: Box<context::event::EventHandler<InternalRequest>> = Box::new(DummyEventHandler{counter: event_handler_counter_1.clone(), ids: ids_1});
        let event_handler_2: Box<context::event::EventHandler<InternalRequest>> = Box::new(DummyEventHandler{counter: event_handler_counter_2.clone(), ids: ids_2});
        let event_handler_1 = Rc::new(RefCell::new(event_handler_1));
        let event_handler_2 = Rc::new(RefCell::new(event_handler_2));
        let mut message_event_handler = MessageEventHandler::new(response_handler.clone());
        message_event_handler.register_handler(event_handler_1);
        message_event_handler.register_handler(event_handler_2);
        message_event_handler.handle_event(Request::Message(Rc::new(Builder::new(&uuid1).build())));
        assert_eq!(1, *event_handler_counter_1.borrow());
        message_event_handler.handle_event(Request::Message(Rc::new(Builder::new(&uuid1).build())));
        assert_eq!(2, *event_handler_counter_1.borrow());
        assert_eq!(0, *event_handler_counter_2.borrow());
        assert_eq!(0, *response_handler_counter.borrow());
    }
}
<commit_msg>MessageEventHandler: remove a debug print<commit_after>use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;

use context;
use dispatcher::request::{InternalRequest, Request, RequestHandler};
use dispatcher::response::ResponseHandler;
use dispatcher::Response;
use context::event::EventHandler;
use message::{Message, PatternId};
use reactor;

pub struct MessageEventHandler {
    handlers: HashMap<PatternId, Vec<Rc<RefCell<Box<context::event::EventHandler<InternalRequest>>>>>>,
    keyless_handlers: Vec<Rc<RefCell<Box<context::event::EventHandler<InternalRequest>>>>>,
    response_handler: Rc<RefCell<Box<ResponseHandler<Response>>>>,
}

impl MessageEventHandler {
    pub fn new(response_handler: Rc<RefCell<Box<ResponseHandler<Response>>>>) -> MessageEventHandler {
        MessageEventHandler{
            handlers: HashMap::new(),
            keyless_handlers: Vec::new(),
            response_handler: response_handler
        }
    }

    pub fn register_handler(&mut self, handler: Rc<RefCell<Box<context::event::EventHandler<InternalRequest>>>>) {
        let cloned_handler = handler.clone();
        if handler.borrow().handlers().is_empty() {
            self.keyless_handlers.push(cloned_handler);
        } else {
            for key in cloned_handler.borrow().handlers() {
                let handlers = self.handlers.entry(key.clone()).or_insert(Vec::new());
                handlers.push(cloned_handler.clone());
            }
        }
    }

    pub fn call_handlers_by_id(&mut self, id: &PatternId, event: Rc<Message>) {
        if let Some(handlers) = self.handlers.get_mut(id) {
            for i in handlers.iter_mut() {
                if let Some(result) = i.borrow_mut().handle_event(Request::Message(event.clone())) {
                    for i in result.into_iter() {
                        self.response_handler.borrow_mut().handle_response(i.into());
                    }
                }
            }
        } else {
            println!("no handler found for id: {:?}", id);
        }
    }
}

impl reactor::EventHandler<InternalRequest> for MessageEventHandler {
    type Handler = RequestHandler;
    fn handle_event(&mut self, event: InternalRequest) {
        if let Request::Message(event) = event {
            println!("message event");
            if let Some(id) = event.name() {
                self.call_handlers_by_id(id, event.clone());
            } else {
                let id = event.uuid();
                self.call_handlers_by_id(id, event.clone());
            }

            for i in self.keyless_handlers.iter_mut() {
                i.borrow_mut().handle_event(Request::Message(event.clone()));
            }
        } else {
            unreachable!("MessageEventHandler should only handle Message events");
        }
    }
    fn handler(&self) -> Self::Handler {
        RequestHandler::Message
    }
}

#[cfg(test)]
mod test {
    use uuid::Uuid;
    use std::cell::RefCell;
    use std::rc::Rc;

    use action::ExecResult;
    use context;
    use dispatcher::request::{InternalRequest, Request};
    use dispatcher::response::ResponseHandler;
    use dispatcher::Response;
    use message::{Builder, PatternId};
    use reactor::EventHandler;

    use super::MessageEventHandler;

    struct DummyResponseHandler(Rc<RefCell<i32>>);

    impl ResponseHandler<Response> for DummyResponseHandler {
        fn handle_response(&mut self, _: Response) {
            *self.0.borrow_mut() += 1;
        }
    }

    struct DummyEventHandler {
        counter: Rc<RefCell<i32>>,
        ids: Vec<PatternId>
    }

    impl context::event::EventHandler<InternalRequest> for DummyEventHandler {
        fn handle_event(&mut self, _: InternalRequest) -> Option<Vec<ExecResult>> {
            *self.counter.borrow_mut() += 1;
            None
        }
        fn handlers(&self) -> &[PatternId] {
            &self.ids
        }
    }

    #[test]
    fn test_given_message_event_handler_when_it_receives_a_message_then_it_calls_the_right_handler() {
        let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
        let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
        let response_handler_counter = Rc::new(RefCell::new(0));
        let response_handler: Box<ResponseHandler<Response>> = Box::new(DummyResponseHandler(response_handler_counter.clone()));
        let response_handler = Rc::new(RefCell::new(response_handler));
        let ids_1 = vec![ PatternId::Uuid(Uuid::parse_str(&uuid1).unwrap()) ];
        let ids_2 = vec![ PatternId::Uuid(Uuid::parse_str(&uuid2).unwrap()) ];
        let event_handler_counter_1 = Rc::new(RefCell::new(0));
        let event_handler_counter_2 = Rc::new(RefCell::new(0));
        let event_handler_1: Box<context::event::EventHandler<InternalRequest>> = Box::new(DummyEventHandler{counter: event_handler_counter_1.clone(), ids: ids_1});
        let event_handler_2: Box<context::event::EventHandler<InternalRequest>> = Box::new(DummyEventHandler{counter: event_handler_counter_2.clone(), ids: ids_2});
        let event_handler_1 = Rc::new(RefCell::new(event_handler_1));
        let event_handler_2 = Rc::new(RefCell::new(event_handler_2));
        let mut message_event_handler = MessageEventHandler::new(response_handler.clone());
        message_event_handler.register_handler(event_handler_1);
        message_event_handler.register_handler(event_handler_2);
        message_event_handler.handle_event(Request::Message(Rc::new(Builder::new(&uuid1).build())));
        assert_eq!(1, *event_handler_counter_1.borrow());
        message_event_handler.handle_event(Request::Message(Rc::new(Builder::new(&uuid1).build())));
        assert_eq!(2, *event_handler_counter_1.borrow());
        assert_eq!(0, *event_handler_counter_2.borrow());
        assert_eq!(0, *response_handler_counter.borrow());
    }
}
<|endoftext|>