<commit_before>/*!
 * SMTP commands library
 *
 * RFC 5321 : http://tools.ietf.org/html/rfc5321#section-4.1
 */

use std::fmt;
use std::io;

/*
 * HELO <SP> <domain> <CRLF>
 * MAIL <SP> FROM:<reverse-path> <CRLF>
 * RCPT <SP> TO:<forward-path> <CRLF>
 * DATA <CRLF>
 * RSET <CRLF>
 * SEND <SP> FROM:<reverse-path> <CRLF>
 * SOML <SP> FROM:<reverse-path> <CRLF>
 * SAML <SP> FROM:<reverse-path> <CRLF>
 * VRFY <SP> <string> <CRLF>
 * EXPN <SP> <string> <CRLF>
 * HELP [<SP> <string>] <CRLF>
 * NOOP <CRLF>
 * QUIT <CRLF>
 * TURN <CRLF>
 */

/// List of SMTP commands
#[deriving(Eq,Clone)]
pub enum Command {
    Hello,
    Ehello,
    Mail,
    Recipient,
    Data,
    Reset,
    SendMail,
    SendOrMail,
    SendAndMail,
    Verify,
    Expand,
    Help,
    Noop,
    Quit,
    /// Deprecated in RFC 5321
    Turn,
}

impl Command {
    /// Tell if the command accetps an string argument.
    pub fn takes_argument(&self) -> bool{
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => true,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }

    /// Tell if an argument is needed by the command.
    pub fn needs_argument(&self) -> bool {
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => false,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }
}

impl ToStr for Command {
    /// Get the name of a command.
    fn to_str(&self) -> ~str {
        match *self {
            Hello           => ~"HELO",
            Ehello          => ~"EHLO",
            Mail            => ~"MAIL",
            Recipient       => ~"RCPT",
            Data            => ~"DATA",
            Reset           => ~"RSET",
            SendMail        => ~"SEND",
            SendOrMail      => ~"SOML",
            SendAndMail     => ~"SAML",
            Verify          => ~"VRFY",
            Expand          => ~"EXPN",
            Help            => ~"HELP",
            Noop            => ~"NOOP",
            Quit            => ~"QUIT",
            Turn            => ~"TURN",
        }
    }
}

impl FromStr for Command {
    /// Get the Command from its name.
    fn from_str(command: &str) -> Option<Command> {
        if !command.is_ascii() {
            return None;
        }
        match command {
            "HELO" => Some(Hello),
            "EHLO" => Some(Ehello),
            "MAIL" => Some(Mail),
            "RCPT" => Some(Recipient),
            "DATA" => Some(Data),
            "RSET" => Some(Reset),
            "SEND" => Some(SendMail),
            "SOML" => Some(SendOrMail),
            "SAML" => Some(SendAndMail),
            "VRFY" => Some(Verify),
            "EXPN" => Some(Expand),
            "HELP" => Some(Help),
            "NOOP" => Some(Noop),
            "QUIT" => Some(Quit),
            "TURN" => Some(Turn),
            _      => None,
        }
    }
}

impl fmt::Show for Command {
    /// Format SMTP command display
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), io::IoError> {
        f.buf.write(match *self {
            Ehello        => "EHLO".as_bytes(),
            Hello         => "HELO".as_bytes(),
            Mail          => "MAIL FROM:".as_bytes(),
            Recipient     => "RCPT TO:".as_bytes(),
            Data          => "DATA".as_bytes(),
            Reset         => "RSET".as_bytes(),
            SendMail      => "SEND TO:".as_bytes(),
            SendOrMail    => "SOML TO:".as_bytes(),
            SendAndMail   => "SAML TO:".as_bytes(),
            Verify        => "VRFY".as_bytes(),
            Expand        => "EXPN".as_bytes(),
            Help          => "HELP".as_bytes(),
            Noop          => "NOOP".as_bytes(),
            Quit          => "QUIT".as_bytes(),
            Turn          => "TURN".as_bytes()
        })
    }
}

/// Structure for a complete SMTP command, containing an optionnal string argument.
pub struct SmtpCommand {
    command: Command,
    argument: Option<~str>
}

impl SmtpCommand {
    /// Return a new structure from the name of the command and an optionnal argument.
    pub fn new(command: Command, argument: Option<~str>) -> SmtpCommand {
        match (command.takes_argument(), command.needs_argument(), argument.clone()) {
            (true, true, None)      => fail!("Wrong SMTP syntax : argument needed"),
            (false, false, Some(x)) => fail!("Wrong SMTP syntax : {:s} not accepted", x),
            _                       => SmtpCommand {command: command, argument: argument}
        }
    }

    /// Return the formatted command, ready to be used in an SMTP session.
    pub fn get_formatted_command(&self) -> ~str {
        match (self.command.takes_argument(), self.command.needs_argument(), self.argument.clone()) {
            (true, _, Some(argument)) => format!("{} {}", self.command, argument),
            (_, false, None)   => format!("{}", self.command),
            _                  => fail!("Wrong SMTP syntax")
        }
    }
}

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

    #[test]
    fn test_command_parameters() {
        assert!((super::Help).takes_argument() == true);
        assert!((super::Reset).takes_argument() == false);
        assert!((super::Hello).needs_argument() == true);
    }

    #[test]
    fn test_get_simple_command() {
        assert!(SmtpCommand::new(~"TURN", None).get_formatted_command() == ~"TURN");
    }

    #[test]
    fn test_get_argument_command() {
        assert!(SmtpCommand::new(~"EHLO", Some(~"example.example")).get_formatted_command() == ~"EHLO example.example");
    }
}
<commit_msg>Fix tests<commit_after>/*!
 * SMTP commands library
 *
 * RFC 5321 : http://tools.ietf.org/html/rfc5321#section-4.1
 */

use std::fmt;
use std::io;

/*
 * HELO <SP> <domain> <CRLF>
 * MAIL <SP> FROM:<reverse-path> <CRLF>
 * RCPT <SP> TO:<forward-path> <CRLF>
 * DATA <CRLF>
 * RSET <CRLF>
 * SEND <SP> FROM:<reverse-path> <CRLF>
 * SOML <SP> FROM:<reverse-path> <CRLF>
 * SAML <SP> FROM:<reverse-path> <CRLF>
 * VRFY <SP> <string> <CRLF>
 * EXPN <SP> <string> <CRLF>
 * HELP [<SP> <string>] <CRLF>
 * NOOP <CRLF>
 * QUIT <CRLF>
 * TURN <CRLF>
 */

/// List of SMTP commands
#[deriving(Eq,Clone)]
pub enum Command {
    Hello,
    Ehello,
    Mail,
    Recipient,
    Data,
    Reset,
    SendMail,
    SendOrMail,
    SendAndMail,
    Verify,
    Expand,
    Help,
    Noop,
    Quit,
    /// Deprecated in RFC 5321
    Turn,
}

impl Command {
    /// Tell if the command accetps an string argument.
    pub fn takes_argument(&self) -> bool{
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => true,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }

    /// Tell if an argument is needed by the command.
    pub fn needs_argument(&self) -> bool {
        match *self {
            Ehello        => true,
            Hello         => true,
            Mail          => true,
            Recipient     => true,
            Data          => false,
            Reset         => false,
            SendMail      => true,
            SendOrMail    => true,
            SendAndMail   => true,
            Verify        => true,
            Expand        => true,
            Help          => false,
            Noop          => false,
            Quit          => false,
            Turn          => false,
        }
    }
}

impl ToStr for Command {
    /// Get the name of a command.
    fn to_str(&self) -> ~str {
        match *self {
            Hello           => ~"HELO",
            Ehello          => ~"EHLO",
            Mail            => ~"MAIL",
            Recipient       => ~"RCPT",
            Data            => ~"DATA",
            Reset           => ~"RSET",
            SendMail        => ~"SEND",
            SendOrMail      => ~"SOML",
            SendAndMail     => ~"SAML",
            Verify          => ~"VRFY",
            Expand          => ~"EXPN",
            Help            => ~"HELP",
            Noop            => ~"NOOP",
            Quit            => ~"QUIT",
            Turn            => ~"TURN",
        }
    }
}

impl FromStr for Command {
    /// Get the Command from its name.
    fn from_str(command: &str) -> Option<Command> {
        if !command.is_ascii() {
            return None;
        }
        match command {
            "HELO" => Some(Hello),
            "EHLO" => Some(Ehello),
            "MAIL" => Some(Mail),
            "RCPT" => Some(Recipient),
            "DATA" => Some(Data),
            "RSET" => Some(Reset),
            "SEND" => Some(SendMail),
            "SOML" => Some(SendOrMail),
            "SAML" => Some(SendAndMail),
            "VRFY" => Some(Verify),
            "EXPN" => Some(Expand),
            "HELP" => Some(Help),
            "NOOP" => Some(Noop),
            "QUIT" => Some(Quit),
            "TURN" => Some(Turn),
            _      => None,
        }
    }
}

impl fmt::Show for Command {
    /// Format SMTP command display
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), io::IoError> {
        f.buf.write(match *self {
            Ehello        => "EHLO".as_bytes(),
            Hello         => "HELO".as_bytes(),
            Mail          => "MAIL FROM:".as_bytes(),
            Recipient     => "RCPT TO:".as_bytes(),
            Data          => "DATA".as_bytes(),
            Reset         => "RSET".as_bytes(),
            SendMail      => "SEND TO:".as_bytes(),
            SendOrMail    => "SOML TO:".as_bytes(),
            SendAndMail   => "SAML TO:".as_bytes(),
            Verify        => "VRFY".as_bytes(),
            Expand        => "EXPN".as_bytes(),
            Help          => "HELP".as_bytes(),
            Noop          => "NOOP".as_bytes(),
            Quit          => "QUIT".as_bytes(),
            Turn          => "TURN".as_bytes()
        })
    }
}

/// Structure for a complete SMTP command, containing an optionnal string argument.
pub struct SmtpCommand {
    command: Command,
    argument: Option<~str>
}

impl SmtpCommand {
    /// Return a new structure from the name of the command and an optionnal argument.
    pub fn new(command: Command, argument: Option<~str>) -> SmtpCommand {
        match (command.takes_argument(), command.needs_argument(), argument.clone()) {
            (true, true, None)      => fail!("Wrong SMTP syntax : argument needed"),
            (false, false, Some(x)) => fail!("Wrong SMTP syntax : {:s} not accepted", x),
            _                       => SmtpCommand {command: command, argument: argument}
        }
    }

    /// Return the formatted command, ready to be used in an SMTP session.
    pub fn get_formatted_command(&self) -> ~str {
        match (self.command.takes_argument(), self.command.needs_argument(), self.argument.clone()) {
            (true, _, Some(argument)) => format!("{} {}", self.command, argument),
            (_, false, None)   => format!("{}", self.command),
            _                  => fail!("Wrong SMTP syntax")
        }
    }
}

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

    #[test]
    fn test_command_parameters() {
        assert!((super::Help).takes_argument() == true);
        assert!((super::Reset).takes_argument() == false);
        assert!((super::Hello).needs_argument() == true);
    }

    #[test]
    fn test_get_simple_command() {
        assert!(SmtpCommand::new(super::Turn, None).get_formatted_command() == ~"TURN");
    }

    #[test]
    fn test_get_argument_command() {
        assert!(SmtpCommand::new(super::Ehello, Some(~"example.example")).get_formatted_command() == ~"EHLO example.example");
    }
}
<|endoftext|>


<commit_before>/// eventbox is a simple abstract of event handling
///
/// The concept is:
///
/// An eventbox stores a vector of events, the order does not mather.
///
/// 1. the sender and receiver of a/some events share an eventbox
/// 2. when some event happans, the sender push the event/value into the eventbox.
/// 3. Meanwhile the receiver is waiting(blocked).
/// 4. When some event happen, eventbox will notify the receiver.
///
/// # Examples
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// use fzf_rs::util::eventbox::EventBox;
/// let mut eb = Arc::new(EventBox::new());
/// let mut eb2 = eb.clone();
///
/// thread::spawn(move || {
///     eb2.set(10, Box::new(20));
/// });
///
/// let val: i32 = *eb.wait_for(10).downcast().unwrap();
/// assert_eq!(20, val);
/// ```

use std::sync::{Condvar, Mutex};
use std::collections::HashMap;
use std::any::Any;
use std::mem;
use std::hash::Hash;

pub type Value = Box<Any + 'static + Send>;
pub type Events<T> = HashMap<T, Value>;

struct EventData<T> {
    events: Events<T>,
    ignore: Events<T>,
}

pub struct EventBox<T> {
    mutex: Mutex<EventData<T>>,
    cond: Condvar,
}

impl<T: Hash + Eq + Copy> EventBox<T> {
    pub fn new() -> Self {
        EventBox {
            mutex: Mutex::new(EventData{events: HashMap::new(), ignore: HashMap::new()}),
            cond: Condvar::new(),
        }
    }

    /// wait: wait for an event(any) to fire
    /// if any event is triggered, run callback on events vector
    pub fn wait(&self) -> Events<T> {
        let mut data = self.mutex.lock().unwrap();
        let events = mem::replace(&mut data.events, HashMap::new());
        let num_of_events = events.len();
        if num_of_events == 0 {
            let _ = self.cond.wait(data);
            let mut data = self.mutex.lock().unwrap();
            mem::replace(&mut data.events, HashMap::new())
        } else {
            events
        }
    }

    /// set: fires an event
    pub fn set(&self, e: T, value: Value) {
        let mut data = self.mutex.lock().unwrap();
        {
            let val = data.events.entry(e).or_insert(Box::new(0));
            *val = value;
        }
        if !data.ignore.contains_key(&e) {
            self.cond.notify_all();
        }
    }

    /// clear the event map
    pub fn clear(&self) {
        let mut data = self.mutex.lock().unwrap();
        data.events.clear();
    }

    // peek at the event box to check whether event had been set or not
    pub fn peek(&self, event: T) -> bool {
        let data = self.mutex.lock().unwrap();
        data.events.contains_key(&event)
    }

    // remove events from ignore table
    pub fn watch(&self, events: &Vec<T>) {
        let mut data = self.mutex.lock().unwrap();
        for e in events {
            data.ignore.remove(e);
        }
    }

    // add events from ignore table
    pub fn unwatch(&self, events: &Vec<T>) {
        let mut data = self.mutex.lock().unwrap();
        for e in events {
            data.ignore.insert(*e, Box::new(true));
        }
    }

    pub fn wait_for(&self, event: T) -> Value {
        'event_found: loop {
            for (e, val) in self.wait() {
                if e == event {
                    return val
                }
            }
        }
    }

    pub fn is_empty(&self) -> bool {
        let data = self.mutex.lock().unwrap();
        data.events.len() == 0
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::thread;
    use std::sync::{Arc, Mutex};
    use std::time::Duration;

    #[test]
    fn test_wait() {
        const NUM_OF_EVENTS: i32 = 4;

        // create `NUM_OF_EVENTS` threads that set the return value to
        // their thread number, the sum up the value and compare it in
        // the main thread.

        let eb = Arc::new(EventBox::new());
        let counter = Arc::new(Mutex::new(0));
        for i in 1..(NUM_OF_EVENTS+1) {
            let eb_clone = eb.clone();
            let counter_clone = counter.clone();
            thread::spawn(move || {
                eb_clone.set(i, Box::new(i));
                let mut count = counter_clone.lock().unwrap();
                *count += 1;
            });
        }

        // wait till all events are set
        loop {
            thread::sleep(Duration::from_millis(100));
            let count = counter.lock().unwrap();
            if *count == NUM_OF_EVENTS {
                break;
            }
        }

        let mut total: i32 = 0;
        for (_, val) in eb.wait() {
            total += *val.downcast().unwrap();
        }

        assert_eq!((1..(NUM_OF_EVENTS+1)).fold(0, |x, acc| acc+x), total);
    }

    #[test]
    fn test_wait_for() {
        let eb = Arc::new(EventBox::new());
        let eb2 = eb.clone();

        thread::spawn(move || {
            eb2.set(10, Box::new(20));
        });

        let val: i32 = *eb.wait_for(10).downcast().unwrap();
        assert_eq!(20, val);
    }

    #[test]
    fn test_unwatch_set() {
        const NUM_OF_EVENTS: i32 = 4;
        let eb = Arc::new(EventBox::new());

        // this time, we ignore event NO. NUM_OF_EVENTS
        // note that unwatch will not trigger the event notification, but the
        // value are actually set.
        eb.unwatch(&vec![NUM_OF_EVENTS]);

        let counter = Arc::new(Mutex::new(0));
        for i in 1..(NUM_OF_EVENTS+1) {
            let eb_clone = eb.clone();
            let counter_clone = counter.clone();
            thread::spawn(move || {
                eb_clone.set(i, Box::new(i));
                let mut count = counter_clone.lock().unwrap();
                *count += 1;
            });
        }

        // wait till all events are set
        loop {
            thread::sleep(Duration::from_millis(100));
            let count = counter.lock().unwrap();
            if *count == NUM_OF_EVENTS {
                break;
            }
        }

        let mut total: i32 = 0;
        for (_, val) in eb.wait() {
            total += *val.downcast().unwrap();
        }

        assert_eq!((1..(NUM_OF_EVENTS+1)).fold(0, |x, acc| acc+x), total);
    }

    #[test]
    fn test_unwatch_notify() {
        // unwatched event will not trigger notification

        let eb = Arc::new(EventBox::new());

        eb.unwatch(&vec![1]);

        let eb_clone1 = eb.clone();

        let which_one = Arc::new(Mutex::new(1));
        let which_one_clone = which_one.clone();

        let wait = thread::spawn(move || {
            for (_, _) in eb.wait() {
                let mut data = which_one.lock().unwrap();
                assert_eq!(2, *data);
            }
        });

        thread::spawn(move || {
            eb_clone1.set(1, Box::new(1));

            // to ensure that the `wait` in main thread have time to trigger.
            // of course, the expected behavior is that it will not.
            thread::sleep(Duration::from_millis(100));

            let mut data = which_one_clone.lock().unwrap();
            *data = 2;
            eb_clone1.set(2, Box::new(2));
        });

        wait.join();
    }
}
<commit_msg>[eventbox] add throttle version of set<commit_after>/// eventbox is a simple abstract of event handling
///
/// The concept is:
///
/// An eventbox stores a vector of events, the order does not mather.
///
/// 1. the sender and receiver of a/some events share an eventbox
/// 2. when some event happans, the sender push the event/value into the eventbox.
/// 3. Meanwhile the receiver is waiting(blocked).
/// 4. When some event happen, eventbox will notify the receiver.
///
/// # Examples
/// ```
/// use std::sync::Arc;
/// use std::thread;
/// use skim::util::eventbox::EventBox;
/// let mut eb = Arc::new(EventBox::new());
/// let mut eb2 = eb.clone();
///
/// thread::spawn(move || {
///     eb2.set(10, Box::new(20));
/// });
///
/// let val: i32 = *eb.wait_for(10).downcast().unwrap();
/// assert_eq!(20, val);
/// ```

use std::sync::{Condvar, Mutex, Arc};
use std::collections::{HashMap, HashSet};
use std::any::Any;
use std::mem;
use std::hash::Hash;
use std::thread;
use std::time::Duration;

pub type Value = Box<Any + 'static + Send>;
pub type Events<T> = HashMap<T, Value>;

struct EventData<T> {
    events:    Events<T>,
    lazy:      HashSet<T>,
    blocked:   HashSet<T>,
    throttled: Events<T>,
}

pub struct EventBox<T> {
    mutex: Arc<Mutex<EventData<T>>>,
    cond: Arc<Condvar>,
}

impl<T> EventBox<T> where T: Hash + Eq + Copy + 'static + Send {
    pub fn new() -> Self {
        EventBox {
            mutex: Arc::new(Mutex::new(EventData{events:    HashMap::new(),
                                                 lazy:      HashSet::new(),
                                                 throttled: HashMap::new(),
                                                 blocked:   HashSet::new()})),
            cond: Arc::new(Condvar::new()),
        }
    }

    /// wait: wait for an event(any) to fire
    /// if any event is triggered, run callback on events vector
    pub fn wait(&self) -> Events<T> {
        let mut data = self.mutex.lock().unwrap();
        let events = mem::replace(&mut data.events, HashMap::new());
        let num_of_events = events.len();
        if num_of_events == 0 {
            let _ = self.cond.wait(data);
            let mut data = self.mutex.lock().unwrap();
            mem::replace(&mut data.events, HashMap::new())
        } else {
            events
        }
    }

    /// set: fires an event
    pub fn set(&self, e: T, value: Value) {
        set_event(&self.mutex, &self.cond, e, value)
    }

    /// set_throttle: limit the number of an event within a timeout.
    ///  X X XX XY Y YY Y
    /// |        |        |
    ///  X        X        Y
    pub fn set_throttle(&self, e: T, value: Value, timeout: u64) {
        set_event_throttle(&self.mutex, &self.cond, e, value, timeout, false);
    }

    /// clear the event map
    pub fn clear(&self) {
        let mut data = self.mutex.lock().unwrap();
        data.events.clear();
    }

    // peek at the event box to check whether event had been set or not
    pub fn peek(&self, event: T) -> bool {
        let data = self.mutex.lock().unwrap();
        data.events.contains_key(&event)
    }

    // remove events from lazy table
    pub fn watch(&self, events: &Vec<T>) {
        let mut data = self.mutex.lock().unwrap();
        for e in events {
            data.lazy.remove(e);
        }
    }

    // add events from lazy table
    pub fn unwatch(&self, events: &Vec<T>) {
        let mut data = self.mutex.lock().unwrap();
        for e in events {
            data.lazy.insert(*e);
        }
    }

    pub fn wait_for(&self, event: T) -> Value {
        'event_found: loop {
            for (e, val) in self.wait() {
                if e == event {
                    return val
                }
            }
        }
    }

    pub fn is_empty(&self) -> bool {
        let data = self.mutex.lock().unwrap();
        data.events.len() == 0
    }
}

fn set_event<T>(mutex: &Arc<Mutex<EventData<T>>>, cond: &Arc<Condvar>, e: T, value: Value)
    where T: Hash + Eq + Copy + 'static + Send {
    let mut data = mutex.lock().unwrap();
    {

        let val = data.events.entry(e).or_insert(Box::new(0));
        *val = value;
    }

    if !data.lazy.contains(&e) {
        cond.notify_all();
    }
}

fn set_event_throttle<T>(mutex: &Arc<Mutex<EventData<T>>>, cond: &Arc<Condvar>, e: T, value: Value, timeout: u64, from_thread: bool)
    where T: Hash + Eq + Copy + 'static + Send {
    {
        let mut data = mutex.lock().unwrap();
        if !from_thread && data.blocked.contains(&e) {
            let val = data.throttled.entry(e).or_insert(Box::new(0));
            *val = value;
            return;
        } else {
            data.blocked.insert(e);
        }
    }

    set_event(&mutex, &cond, e, value);

    let mutex = mutex.clone();
    let cond = cond.clone();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(timeout));
        let mut remaining = {
            let mut data = mutex.lock().unwrap();
            data.throttled.remove(&e)
        };

        remaining.map_or_else(
            || {
                let mut data = mutex.lock().unwrap();
                let _ = data.blocked.remove(&e);
            },
            |v| {
                set_event_throttle(&mutex, &cond, e, v, timeout, true);
            });
    });
}

#[cfg(test)]
mod test {
    use super::*;
    use std::thread;
    use std::sync::{Arc, Mutex};
    use std::time::{Duration, Instant};

    #[test]
    fn test_wait() {
        const NUM_OF_EVENTS: i32 = 4;

        // create `NUM_OF_EVENTS` threads that set the return value to
        // their thread number, the sum up the value and compare it in
        // the main thread.

        let eb = Arc::new(EventBox::new());
        let counter = Arc::new(Mutex::new(0));
        for i in 1..(NUM_OF_EVENTS+1) {
            let eb_clone = eb.clone();
            let counter_clone = counter.clone();
            thread::spawn(move || {
                eb_clone.set(i, Box::new(i));
                let mut count = counter_clone.lock().unwrap();
                *count += 1;
            });
        }

        // wait till all events are set
        loop {
            thread::sleep(Duration::from_millis(100));
            let count = counter.lock().unwrap();
            if *count == NUM_OF_EVENTS {
                break;
            }
        }

        let mut total: i32 = 0;
        for (_, val) in eb.wait() {
            total += *val.downcast().unwrap();
        }

        assert_eq!((1..(NUM_OF_EVENTS+1)).fold(0, |x, acc| acc+x), total);
    }

    #[test]
    fn test_wait_for() {
        let eb = Arc::new(EventBox::new());
        let eb2 = eb.clone();

        thread::spawn(move || {
            eb2.set(10, Box::new(20));
        });

        let val: i32 = *eb.wait_for(10).downcast().unwrap();
        assert_eq!(20, val);
    }

    #[test]
    fn test_unwatch_set() {
        const NUM_OF_EVENTS: i32 = 4;
        let eb = Arc::new(EventBox::new());

        // this time, we lazy event NO. NUM_OF_EVENTS
        // note that unwatch will not trigger the event notification, but the
        // value are actually set.
        eb.unwatch(&vec![NUM_OF_EVENTS]);

        let counter = Arc::new(Mutex::new(0));
        for i in 1..(NUM_OF_EVENTS+1) {
            let eb_clone = eb.clone();
            let counter_clone = counter.clone();
            thread::spawn(move || {
                eb_clone.set(i, Box::new(i));
                let mut count = counter_clone.lock().unwrap();
                *count += 1;
            });
        }

        // wait till all events are set
        loop {
            thread::sleep(Duration::from_millis(100));
            let count = counter.lock().unwrap();
            if *count == NUM_OF_EVENTS {
                break;
            }
        }

        let mut total: i32 = 0;
        for (_, val) in eb.wait() {
            total += *val.downcast().unwrap();
        }

        assert_eq!((1..(NUM_OF_EVENTS+1)).fold(0, |x, acc| acc+x), total);
    }

    #[test]
    fn test_unwatch_notify() {
        // unwatched event will not trigger notification

        let eb = Arc::new(EventBox::new());

        eb.unwatch(&vec![1]);

        let eb_clone1 = eb.clone();

        let which_one = Arc::new(Mutex::new(1));
        let which_one_clone = which_one.clone();

        let wait = thread::spawn(move || {
            for (_, _) in eb.wait() {
                let mut data = which_one.lock().unwrap();
                assert_eq!(2, *data);
            }
        });

        thread::spawn(move || {
            eb_clone1.set(1, Box::new(1));

            // to ensure that the `wait` in main thread have time to trigger.
            // of course, the expected behavior is that it will not.
            thread::sleep(Duration::from_millis(100));

            let mut data = which_one_clone.lock().unwrap();
            *data = 2;
            eb_clone1.set(2, Box::new(2));
        });

        wait.join();
    }

    // Not including this test, because we should not rely on eventbox to do the dispatching at
    // exact time. In this sense, it is better not to include this in the test suite.
    //
    //#[test]
    //fn test_set_throttle() {
        //let eb = Arc::new(EventBox::new());

        //let eb_clone = eb.clone();
        //thread::spawn(move || {
            //// will receive: 0, 2, 5, 7
            //for i in 0..10 {
                //eb_clone.set_throttle(1, Box::new(i), 20);
                //thread::sleep(Duration::from_millis(7));
            //}
        //});

        //let mut total: i32 = 0;
        //let timer = Instant::now();
        //loop {

            //if eb.peek(1) {
                //for (_, val) in eb.wait() {
                    //let x = *val.downcast().unwrap();
                    //println!("x = {}", x);
                    //total += x;
                //}
            //}

            //let time = timer.elapsed();
            //let mills = (time.as_secs()*1000) as u32 + time.subsec_nanos()/1000/1000;
            //if mills > 100 {
                //break;
            //}
        //}

        //assert_eq!(total, 24);
    //}

}
<|endoftext|>


<commit_before>use ::geometry::*;
use arrayvec;
trait SliceUp: Sized {
    type PerSlice: Iterator<Item=Self>;
    type Out: Iterator<Item=Self::PerSlice>;
    fn slice_up_x(&self, planes: PlaneSet) -> Self::Out;
    fn slice_up_y(&self, planes: PlaneSet) -> Self::Out;
}

type LineIter = ::std::option::IntoIter<Line>;

#[derive(Debug)]
struct LineSliceIter {
    l: Line,
    m: f32,
    c: f32,
    planes: PlaneSet,
    i: usize
}

impl Iterator for LineSliceIter {
    type Item = LineIter;
    fn next(&mut self) -> Option<LineIter> {
        if self.i >= self.planes.count {
            return None
        }
        if self.m == 0.0 {
            self.i += 1;
            return Some(Some(self.l).into_iter())
        }
        let lower = self.i as f32;
        let upper = lower + 1.0;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let mut lower_t = (lower_d - self.c) / self.m;
        let mut upper_t = (upper_d - self.c) / self.m;
        lower_t = lower_t.max(0.0).min(1.0);
        upper_t = upper_t.max(0.0).min(1.0);
        if self.m < 0.0 {
            ::std::mem::swap(&mut lower_t, &mut upper_t);
        }
        self.i += 1;
        if lower_t != upper_t {
            let p = &self.l.p;
            let v = p[1] - p[0];
            Some(Some(Line {
                p: [p[0] + v * lower_t,
                    p[0] + v * upper_t]
            }).into_iter())
        } else {
            Some(None.into_iter())
        }
    }
}

impl SliceUp for Line {
    type PerSlice = LineIter;
    type Out = LineSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].x - p[0].x,
            c: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].y - p[0].y,
            c: p[0].y
        }
    }
}

type CurveIter = arrayvec::IntoIter<[Curve; 2]>;

struct CurveSliceIter {
    curve: Curve,
    planes: PlaneSet,
    i: usize,
    a: f32,
    b: f32,
    c_shift: f32
}

impl Iterator for CurveSliceIter {
    type Item = CurveIter;
    fn next(&mut self) -> Option<Self::Item> {
        use arrayvec::ArrayVec;
        use geometry::RealQuadraticSolution as RQS;
        use geometry::solve_quadratic_real as solve;
        use geometry::Cut;
        if self.i >= self.planes.count {
            return None
        }
        let lower = self.i as f32;
        self.i += 1;
        let upper = lower + self.planes.step;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let l_sol = solve(self.a, self.b, self.c_shift - lower_d);
        let u_sol = solve(self.a, self.b, self.c_shift - upper_d);
        let mut result = ArrayVec::<[Curve; 2]>::new();
        match (l_sol.in_order(), u_sol.in_order()) {
            (RQS::Two(a, b), RQS::Two(c, d)) => {
                // Two pieces
                let (a, b, c, d) = if self.a > 0.0 {
                    (c, a, b, d)
                } else {
                    (a, c, d, b)
                };
                let (a, b, c, d) = (a.min(1.0).max(0.0),
                                    b.min(1.0).max(0.0),
                                    c.min(1.0).max(0.0),
                                    d.min(1.0).max(0.0));
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
                if c != d {
                    result.push(self.curve.cut_from_to(c, d));
                }
            }
            (RQS::Two(a, b), RQS::None) |
            (RQS::Two(a, b), RQS::Touch(_)) |
            (RQS::None, RQS::Two(a, b)) |
            (RQS::Touch(_), RQS::Two(a, b)) |
            (RQS::One(a), RQS::One(b)) => {
                // One piece
                let (a, b) = if a > b { (b, a) } else { (a, b) };
                let a = a.min(1.0).max(0.0);
                let b = b.min(1.0).max(0.0);
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
            }
            (RQS::All, RQS::None) |
            (RQS::None, RQS::All) => {
                // coincident with one plane
                result.push(self.curve);
            }
            (RQS::None, RQS::None) => if self.a == 0.0 && self.b == 0.0
                && self.c_shift >= lower_d && self.c_shift <= upper_d
            {
                // parallel to planes, inbetween
                result.push(self.curve);
            },
            _ => unreachable!() // impossible
        }
        //println!("{:?}", result);
        Some(result.into_iter())
    }
}

#[derive(Debug)]
struct PlaneSet {
    start: f32,
    step: f32,
    count: usize
}

impl SliceUp for Curve {
    type PerSlice = CurveIter;
    type Out = CurveSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].x - 2.0 * p[1].x + p[2].x,
            b: 2.0 * (p[1].x - p[0].x),
            c_shift: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].y - 2.0 * p[1].y + p[2].y,
            b: 2.0 * (p[1].y - p[0].y),
            c_shift: p[0].y
        }
    }
}

pub fn rasterize<O: FnMut(u32, u32, f32)>(lines: &[Line], curves: &[Curve],
                                          width: u32, height: u32,
                                          mut output: O) {
    use ::std::collections::HashMap;
    let mut lines: Vec<_> = lines.iter().map(|&l| (l, l.bounding_box())).collect();
    lines[..].sort_by(|&(_, ref a), &(_, ref b)| a.min.y.partial_cmp(&b.min.y).unwrap());
    let mut curves: Vec<_> = curves.iter().map(|&c| (c, c.bounding_box())).collect();
    curves[..].sort_by(|&(_, ref a), &(_, ref b)| a.min.y.partial_cmp(&b.min.y).unwrap());
    let mut y = 0;
    let mut next_line = 0; let mut next_curve = 0;
    let mut active_lines_y  = HashMap::new(); let mut active_curves_y = HashMap::new();
    let mut active_lines_x  = HashMap::new(); let mut active_curves_x = HashMap::new();
    let mut scanline_lines = Vec::new();
    let mut lines_to_remove = Vec::new();
    let mut scanline_curves = Vec::new();
    let mut curves_to_remove = Vec::new();
    while y < height && (next_line != lines.len() || next_curve != curves.len()
        || active_lines_y.len() > 0 || active_curves_y.len() > 0)
    {
        let lower = y as f32;
        let upper = (y + 1) as f32;
        // Add newly active segments
        for &(ref line, ref bb) in lines[next_line..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_lines_y.insert(next_line, line.slice_up_y(planes));
            next_line += 1;
        }
        for &(ref curve, ref bb) in curves[next_curve..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_curves_y.insert(next_curve, curve.slice_up_y(planes));
            next_curve += 1;
        }
        // get y sliced segments for this scanline
        scanline_lines.clear();
        scanline_curves.clear();
        for (k, itr) in active_lines_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for line in itr {
                    scanline_lines.push((line, line.x_bounds()))
                }
            } else {
                lines_to_remove.push(*k);
            }
        }
        for (k, itr) in active_curves_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for curve in itr {
                    scanline_curves.push((curve, curve.x_bounds()))
                }
            } else {
                curves_to_remove.push(*k);
            }
        }
        // remove deactivated segments
        for k in lines_to_remove.drain(..) {
            active_lines_y.remove(&k);
        }
        for k in curves_to_remove.drain(..) {
            active_curves_y.remove(&k);
        }
        // sort scanline for traversal
        scanline_lines.sort_by(|a, b| (a.1).0.partial_cmp(&(b.1).0).unwrap());
        scanline_curves.sort_by(|a, b| (a.1).0.partial_cmp(&(b.1).0).unwrap());
        // Iterate through x, slice scanline segments into each cell. Evaluate, accumulate and output.
        {
            let mut next_line = 0; let mut next_curve = 0;
            let mut x = 0;
            let mut acc = 0.0;
            active_lines_x.clear();
            active_curves_x.clear();
            while x < width && (next_line != scanline_lines.len() || next_curve != scanline_curves.len()
                || active_lines_x.len() > 0 || active_curves_x.len() > 0)
            {
                let offset = vector(x as f32, y as f32);
                let lower = x as f32;
                let upper = (x+1) as f32;
                //add newly active segments
                for &(ref line, (_, ref max)) in scanline_lines[next_line..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_lines_x.insert(next_line, line.slice_up_x(planes));
                    next_line += 1;
                }
                for &(ref curve, (_, ref max)) in scanline_curves[next_curve..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_curves_x.insert(next_curve, curve.slice_up_x(planes));
                    next_curve += 1;
                }
                //process x sliced segments for this pixel
                let mut pixel_value = acc;
                let mut pixel_acc = 0.0;
                for (k, itr) in active_lines_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut line in itr {
                            let p = &mut line.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;

                            let a = p[0].y - p[1].y;
                            let v = (1.0 - (p[0].x + p[1].x) * 0.5) * a;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        lines_to_remove.push(*k);
                    }
                }
                for (k, itr) in active_curves_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut curve in itr {
                            let p = &mut curve.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;
                            p[2] = p[2] - offset;
                            let a = p[0].y - p[2].y;
                            let b = p[0].y - p[1].y;
                            let c = p[1].y - p[2].y;
                            let v = (b*(6.0 - 3.0*p[0].x - 2.0*p[1].x -     p[2].x) +
                                     c*(6.0 -     p[0].x - 2.0*p[1].x - 3.0*p[2].x)) / 6.0;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        curves_to_remove.push(*k);
                    }
                }
                //output
                output(x, y, pixel_value.abs());
                acc += pixel_acc;
                // remove deactivated segments
                for k in lines_to_remove.drain(..) {
                    active_lines_x.remove(&k);
                }
                for k in curves_to_remove.drain(..) {
                    active_curves_x.remove(&k);
                }
                x += 1;
            }
            // fill remaining pixels
            for x in x..width {
                output(x, y, acc.abs());
            }
        }
        y += 1;
    }
    // fill remaining scanlines with 0.0
    for y in y..height {
        for x in 0..width {
            output(x, y, 0.0);
        }
    }
}
<commit_msg>Fix panic sorting PartialOrd<commit_after>use ::geometry::*;
use arrayvec;
 use ordered_float::OrderedFloat;

trait SliceUp: Sized {
    type PerSlice: Iterator<Item=Self>;
    type Out: Iterator<Item=Self::PerSlice>;
    fn slice_up_x(&self, planes: PlaneSet) -> Self::Out;
    fn slice_up_y(&self, planes: PlaneSet) -> Self::Out;
}

type LineIter = ::std::option::IntoIter<Line>;

#[derive(Debug)]
struct LineSliceIter {
    l: Line,
    m: f32,
    c: f32,
    planes: PlaneSet,
    i: usize
}

impl Iterator for LineSliceIter {
    type Item = LineIter;
    fn next(&mut self) -> Option<LineIter> {
        if self.i >= self.planes.count {
            return None
        }
        if self.m == 0.0 {
            self.i += 1;
            return Some(Some(self.l).into_iter())
        }
        let lower = self.i as f32;
        let upper = lower + 1.0;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let mut lower_t = (lower_d - self.c) / self.m;
        let mut upper_t = (upper_d - self.c) / self.m;
        lower_t = lower_t.max(0.0).min(1.0);
        upper_t = upper_t.max(0.0).min(1.0);
        if self.m < 0.0 {
            ::std::mem::swap(&mut lower_t, &mut upper_t);
        }
        self.i += 1;
        if lower_t != upper_t {
            let p = &self.l.p;
            let v = p[1] - p[0];
            Some(Some(Line {
                p: [p[0] + v * lower_t,
                    p[0] + v * upper_t]
            }).into_iter())
        } else {
            Some(None.into_iter())
        }
    }
}

impl SliceUp for Line {
    type PerSlice = LineIter;
    type Out = LineSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].x - p[0].x,
            c: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].y - p[0].y,
            c: p[0].y
        }
    }
}

type CurveIter = arrayvec::IntoIter<[Curve; 2]>;

struct CurveSliceIter {
    curve: Curve,
    planes: PlaneSet,
    i: usize,
    a: f32,
    b: f32,
    c_shift: f32
}

impl Iterator for CurveSliceIter {
    type Item = CurveIter;
    fn next(&mut self) -> Option<Self::Item> {
        use arrayvec::ArrayVec;
        use geometry::RealQuadraticSolution as RQS;
        use geometry::solve_quadratic_real as solve;
        use geometry::Cut;
        if self.i >= self.planes.count {
            return None
        }
        let lower = self.i as f32;
        self.i += 1;
        let upper = lower + self.planes.step;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let l_sol = solve(self.a, self.b, self.c_shift - lower_d);
        let u_sol = solve(self.a, self.b, self.c_shift - upper_d);
        let mut result = ArrayVec::<[Curve; 2]>::new();
        match (l_sol.in_order(), u_sol.in_order()) {
            (RQS::Two(a, b), RQS::Two(c, d)) => {
                // Two pieces
                let (a, b, c, d) = if self.a > 0.0 {
                    (c, a, b, d)
                } else {
                    (a, c, d, b)
                };
                let (a, b, c, d) = (a.min(1.0).max(0.0),
                                    b.min(1.0).max(0.0),
                                    c.min(1.0).max(0.0),
                                    d.min(1.0).max(0.0));
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
                if c != d {
                    result.push(self.curve.cut_from_to(c, d));
                }
            }
            (RQS::Two(a, b), RQS::None) |
            (RQS::Two(a, b), RQS::Touch(_)) |
            (RQS::None, RQS::Two(a, b)) |
            (RQS::Touch(_), RQS::Two(a, b)) |
            (RQS::One(a), RQS::One(b)) => {
                // One piece
                let (a, b) = if a > b { (b, a) } else { (a, b) };
                let a = a.min(1.0).max(0.0);
                let b = b.min(1.0).max(0.0);
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
            }
            (RQS::All, RQS::None) |
            (RQS::None, RQS::All) => {
                // coincident with one plane
                result.push(self.curve);
            }
            (RQS::None, RQS::None) => if self.a == 0.0 && self.b == 0.0
                && self.c_shift >= lower_d && self.c_shift <= upper_d
            {
                // parallel to planes, inbetween
                result.push(self.curve);
            },
            _ => unreachable!() // impossible
        }
        //println!("{:?}", result);
        Some(result.into_iter())
    }
}

#[derive(Debug)]
struct PlaneSet {
    start: f32,
    step: f32,
    count: usize
}

impl SliceUp for Curve {
    type PerSlice = CurveIter;
    type Out = CurveSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].x - 2.0 * p[1].x + p[2].x,
            b: 2.0 * (p[1].x - p[0].x),
            c_shift: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].y - 2.0 * p[1].y + p[2].y,
            b: 2.0 * (p[1].y - p[0].y),
            c_shift: p[0].y
        }
    }
}

pub fn rasterize<O: FnMut(u32, u32, f32)>(lines: &[Line], curves: &[Curve],
                                          width: u32, height: u32,
                                          mut output: O) {
    use ::std::collections::HashMap;
    let mut lines: Vec<_> = lines.iter().map(|&l| (l, l.bounding_box())).collect();
    lines.sort_by_key(|&(_, ref a)| OrderedFloat(a.min.y));
    let mut curves: Vec<_> = curves.iter().map(|&c| (c, c.bounding_box())).collect();
    curves.sort_by_key(|&(_, ref a)| OrderedFloat(a.min.y));
    let mut y = 0;
    let mut next_line = 0; let mut next_curve = 0;
    let mut active_lines_y  = HashMap::new(); let mut active_curves_y = HashMap::new();
    let mut active_lines_x  = HashMap::new(); let mut active_curves_x = HashMap::new();
    let mut scanline_lines = Vec::new();
    let mut lines_to_remove = Vec::new();
    let mut scanline_curves = Vec::new();
    let mut curves_to_remove = Vec::new();
    while y < height && (next_line != lines.len() || next_curve != curves.len()
        || active_lines_y.len() > 0 || active_curves_y.len() > 0)
    {
        let lower = y as f32;
        let upper = (y + 1) as f32;
        // Add newly active segments
        for &(ref line, ref bb) in lines[next_line..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_lines_y.insert(next_line, line.slice_up_y(planes));
            next_line += 1;
        }
        for &(ref curve, ref bb) in curves[next_curve..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_curves_y.insert(next_curve, curve.slice_up_y(planes));
            next_curve += 1;
        }
        // get y sliced segments for this scanline
        scanline_lines.clear();
        scanline_curves.clear();
        for (k, itr) in active_lines_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for line in itr {
                    scanline_lines.push((line, line.x_bounds()))
                }
            } else {
                lines_to_remove.push(*k);
            }
        }
        for (k, itr) in active_curves_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for curve in itr {
                    scanline_curves.push((curve, curve.x_bounds()))
                }
            } else {
                curves_to_remove.push(*k);
            }
        }
        // remove deactivated segments
        for k in lines_to_remove.drain(..) {
            active_lines_y.remove(&k);
        }
        for k in curves_to_remove.drain(..) {
            active_curves_y.remove(&k);
        }
        // sort scanline for traversal
        scanline_lines.sort_by_key(|a| OrderedFloat((a.1).0));
        scanline_curves.sort_by_key(|a| OrderedFloat((a.1).0));
        // Iterate through x, slice scanline segments into each cell. Evaluate, accumulate and output.
        {
            let mut next_line = 0; let mut next_curve = 0;
            let mut x = 0;
            let mut acc = 0.0;
            active_lines_x.clear();
            active_curves_x.clear();
            while x < width && (next_line != scanline_lines.len() || next_curve != scanline_curves.len()
                || active_lines_x.len() > 0 || active_curves_x.len() > 0)
            {
                let offset = vector(x as f32, y as f32);
                let lower = x as f32;
                let upper = (x+1) as f32;
                //add newly active segments
                for &(ref line, (_, ref max)) in scanline_lines[next_line..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_lines_x.insert(next_line, line.slice_up_x(planes));
                    next_line += 1;
                }
                for &(ref curve, (_, ref max)) in scanline_curves[next_curve..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_curves_x.insert(next_curve, curve.slice_up_x(planes));
                    next_curve += 1;
                }
                //process x sliced segments for this pixel
                let mut pixel_value = acc;
                let mut pixel_acc = 0.0;
                for (k, itr) in active_lines_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut line in itr {
                            let p = &mut line.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;

                            let a = p[0].y - p[1].y;
                            let v = (1.0 - (p[0].x + p[1].x) * 0.5) * a;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        lines_to_remove.push(*k);
                    }
                }
                for (k, itr) in active_curves_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut curve in itr {
                            let p = &mut curve.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;
                            p[2] = p[2] - offset;
                            let a = p[0].y - p[2].y;
                            let b = p[0].y - p[1].y;
                            let c = p[1].y - p[2].y;
                            let v = (b*(6.0 - 3.0*p[0].x - 2.0*p[1].x -     p[2].x) +
                                     c*(6.0 -     p[0].x - 2.0*p[1].x - 3.0*p[2].x)) / 6.0;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        curves_to_remove.push(*k);
                    }
                }
                //output
                output(x, y, pixel_value.abs());
                acc += pixel_acc;
                // remove deactivated segments
                for k in lines_to_remove.drain(..) {
                    active_lines_x.remove(&k);
                }
                for k in curves_to_remove.drain(..) {
                    active_curves_x.remove(&k);
                }
                x += 1;
            }
            // fill remaining pixels
            for x in x..width {
                output(x, y, acc.abs());
            }
        }
        y += 1;
    }
    // fill remaining scanlines with 0.0
    for y in y..height {
        for x in 0..width {
            output(x, y, 0.0);
        }
    }
}
<|endoftext|>


<commit_before>//! A CLI tool for inspecting the contents of a DICOM file
//! by printing it in a human readable format.
use dicom::object::open_file;
use dicom_dump::{ColorMode, DumpOptions};
use snafu::ErrorCompat;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

/// Exit code for when an error emerged while reading the DICOM file.
const ERROR_READ: i32 = -2;
/// Exit code for when an error emerged while dumping the file.
const ERROR_PRINT: i32 = -3;

#[cfg(windows)]
fn os_compatibility() -> Result<(), ()> {
    control::set_virtual_terminal(true)
}

#[cfg(not(windows))]
fn os_compatibility() -> Result<(), ()> {
    Ok(())
}

/// Dump the contents of DICOM files
#[derive(Debug, StructOpt)]
struct App {
    /// The DICOM file(s) to read
    #[structopt(required = true)]
    files: Vec<PathBuf>,
    /// whether text value width limit is disabled
    /// (limited to `width` by default)
    #[structopt(long = "no-text-limit")]
    no_text_limit: bool,
    /// the width of the display
    /// (default is to check automatically)
    #[structopt(short = "w", long = "width")]
    width: Option<u32>,
    /// color mode
    #[structopt(long = "color", default_value = "auto")]
    color: ColorMode,
    /// fail if any errors are encountered
    #[structopt(long = "fail-first")]
    fail_first: bool,
}

fn main() {
    os_compatibility().unwrap_or_else(|_| {
        eprintln!("Error setting OS compatibility for colored output");
    });

    let App {
        files: filenames,
        no_text_limit,
        width,
        color,
        fail_first,
    } = App::from_args();

    let width = width
        .or_else(|| term_size::dimensions().map(|(width, _)| width as u32))
        .unwrap_or(120);

    let mut options = DumpOptions::new();
    options.no_text_limit(no_text_limit)
            .width(width)
            .color_mode(color);

    let mut errors = vec![];

    for filename in &filenames {
        println!("{}: ", filename.display());
        match open_file(filename) {
            Err(e) => {
                report(e);
                if fail_first {
                    std::process::exit(ERROR_READ);
                }
                errors.push((filename,ERROR_READ));
            },
            Ok(obj) => {
                if let Err(ref e) = options.dump_file(&obj) {
                    if e.kind() == ErrorKind::BrokenPipe {
                        // handle broken pipe separately with a no-op
                    } else {
                        eprintln!("[ERROR] {}", e);
                        if fail_first {
                        std::process::exit(ERROR_PRINT);
                        }
                    }
                    errors.push((filename,ERROR_PRINT))
                } // else all good
            }
        };
    }
}

fn report<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }

    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}
<commit_msg>Return exit code - number of files that failed to dump<commit_after>//! A CLI tool for inspecting the contents of a DICOM file
//! by printing it in a human readable format.
use dicom::object::open_file;
use dicom_dump::{ColorMode, DumpOptions};
use snafu::ErrorCompat;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

/// Exit code for when an error emerged while reading the DICOM file.
const ERROR_READ: i32 = -2;
/// Exit code for when an error emerged while dumping the file.
const ERROR_PRINT: i32 = -3;

#[cfg(windows)]
fn os_compatibility() -> Result<(), ()> {
    control::set_virtual_terminal(true)
}

#[cfg(not(windows))]
fn os_compatibility() -> Result<(), ()> {
    Ok(())
}

/// Dump the contents of DICOM files
#[derive(Debug, StructOpt)]
struct App {
    /// The DICOM file(s) to read
    #[structopt(required = true)]
    files: Vec<PathBuf>,
    /// whether text value width limit is disabled
    /// (limited to `width` by default)
    #[structopt(long = "no-text-limit")]
    no_text_limit: bool,
    /// the width of the display
    /// (default is to check automatically)
    #[structopt(short = "w", long = "width")]
    width: Option<u32>,
    /// color mode
    #[structopt(long = "color", default_value = "auto")]
    color: ColorMode,
    /// fail if any errors are encountered
    #[structopt(long = "fail-first")]
    fail_first: bool,
}

fn main() {
    os_compatibility().unwrap_or_else(|_| {
        eprintln!("Error setting OS compatibility for colored output");
    });

    let App {
        files: filenames,
        no_text_limit,
        width,
        color,
        fail_first,
    } = App::from_args();

    let width = width
        .or_else(|| term_size::dimensions().map(|(width, _)| width as u32))
        .unwrap_or(120);

    let mut options = DumpOptions::new();
    options.no_text_limit(no_text_limit)
            .width(width)
            .color_mode(color);

    let mut errors: i32 = 0;

    for filename in &filenames {
        println!("{}: ", filename.display());
        match open_file(filename) {
            Err(e) => {
                report(e);
                if fail_first {
                    std::process::exit(ERROR_READ);
                }
                errors = errors + 1;
            },
            Ok(obj) => {
                if let Err(ref e) = options.dump_file(&obj) {
                    if e.kind() == ErrorKind::BrokenPipe {
                        // handle broken pipe separately with a no-op
                    } else {
                        eprintln!("[ERROR] {}", e);
                        if fail_first {
                        std::process::exit(ERROR_PRINT);
                        }
                    }
                    errors = errors + 1;
                } // else all good
            }
        };
    }

    std::process::exit(errors);
}

fn report<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }

    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}
<|endoftext|>


<commit_before>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  /// Failed parsing the "fLaC" header token.
  HeaderParser,
  /// Failed parsing a metadata header.
  MetadataHeaderParser,
  /// Failed parsing the metadata block `StreamInfo`.
  StreamInfoParser,
  /// Failed parsing the metadata block `Padding`.
  PaddingParser,
  /// Failed parsing the metadata block `Application`.
  ApplicationParser,
  /// Failed parsing the metadata block `SeekTable`.
  SeekTableParser,
  /// Failed parsing the metadata block `VorbisComment`.
  VorbisCommentParser,
  /// Failed parsing the metadata block `CueSheet`.
  CueSheetParser,
  /// Failed parsing the metadata block `Picture`.
  PictureParser,
  /// Failed parsing the metadata block `Unknown`.
  UnknownParser,
  BlockingStrategyParser,
  BlockingSampleParser,
  ChannelBitsParser,
  UTF8HeaderParser,
  UTF8BodyParser,
  CRC8Parser,
  FrameFooterParser,
  SubframeParser,
  LeadingZerosParser,
  ConstantParser,
  VerbatimParser,
  FixedParser,
  LPCParser,
  // Invalid Error
  /// A block type, base on the number, that is outside the range (0-126).
  InvalidBlockType,
  InvalidSyncCode,
  InvalidBlockSample,
  InvalidChannelBits,
  InvalidUTF8,
  InvalidCRC8,
  InvalidCRC16,
  InvalidSubframeHeader,
  // Not Found
  /// Some metadata block was not found with a specific filter.
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add parser errors from the frame module<commit_after>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  /// Failed parsing the "fLaC" header token.
  HeaderParser,
  /// Failed parsing a metadata header.
  MetadataHeaderParser,
  /// Failed parsing the metadata block `StreamInfo`.
  StreamInfoParser,
  /// Failed parsing the metadata block `Padding`.
  PaddingParser,
  /// Failed parsing the metadata block `Application`.
  ApplicationParser,
  /// Failed parsing the metadata block `SeekTable`.
  SeekTableParser,
  /// Failed parsing the metadata block `VorbisComment`.
  VorbisCommentParser,
  /// Failed parsing the metadata block `CueSheet`.
  CueSheetParser,
  /// Failed parsing the metadata block `Picture`.
  PictureParser,
  /// Failed parsing the metadata block `Unknown`.
  UnknownParser,
  /// Failed parsing the blocking strategy inside the frame header.
  BlockingStrategyParser,
  /// Failed parsing the blocking sample inside the frame header.
  BlockingSampleParser,
  /// Failed parsing the channel bits inside the frame header.
  ChannelBitsParser,
  /// Failed parsing the UTF-8 header inside the frame header.
  UTF8HeaderParser,
  /// Failed parsing the UTF-8 body inside the frame header.
  UTF8BodyParser,
  /// Failed parsing the CRC-8 inside the frame header.
  CRC8Parser,
  /// Failed parsing the frame footer, also known as the CRC-16.
  FrameFooterParser,
  SubframeParser,
  LeadingZerosParser,
  ConstantParser,
  VerbatimParser,
  FixedParser,
  LPCParser,
  // Invalid Error
  /// A block type, base on the number, that is outside the range (0-126).
  InvalidBlockType,
  InvalidSyncCode,
  InvalidBlockSample,
  InvalidChannelBits,
  InvalidUTF8,
  InvalidCRC8,
  InvalidCRC16,
  InvalidSubframeHeader,
  // Not Found
  /// Some metadata block was not found with a specific filter.
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use map::{Map};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub map: &'a Map,
    pub show_map: bool,
}

impl<'a> Game<'a> {
    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left) {
            self.face_angle -= 0.02;
        }
        if input.has_key(Key::Right) {
            self.face_angle += 0.02;
        }
        if input.has_key(Key::Up) {
            self.pos.x += Float::sin(self.face_angle);
            self.pos.y -= Float::cos(self.face_angle);
        }
        if input.has_key(Key::Down) {
            self.pos.x -= Float::sin(self.face_angle);
            self.pos.y += Float::cos(self.face_angle);
        }
        self.show_map = input.has_key(Key::Tab);
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_lines(&surf);
        } else {
            self.render_cast(&surf);
        }
    }

    fn render_lines(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.map.walls.iter() {
            draw_seg(&surf, &wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        draw_seg(&surf, &LineSeg::new(0.0, 0.0, 0.0, -5.0), 0x00, 0xFF, 0x00);
    }

    fn render_cast(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / 600.0;
                match self.cast_ray(offset) {
                    Some(dist) => {
                        let ray_height = (3000.0 / dist) as usize;
                        let top = if h > ray_height { (h - ray_height) / 2 } else { 0 };
                        let bottom = h - top;
                        let proto_color = (0xFF-(h/2) + ray_height/2);
                        let color = if proto_color > 0xFF { 0xFF } else { proto_color as u8 };
                        for y in 0..top {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in top..bottom {
                            put_px(pixels, w, x, y, color, 0, 0);
                        }
                        for y in bottom..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                    None => {
                        for y in 0..(h/2) {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in (h/2)..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                }
            }
            true
        });
    }

    fn cast_ray(&self, offset: f32) -> Option<f32> {
        let ray = LineSeg::new(
            self.pos.x,
            self.pos.y,
            self.pos.x + 1000.0*Float::sin(self.face_angle + offset),
            self.pos.y - 1000.0*Float::cos(self.face_angle + offset)
        );

        let face_vec = Vec2::new(
             Float::sin(self.face_angle),
            -Float::cos(self.face_angle)
        );

        for wall in self.map.walls.iter() {
            match ray.intersects_at(*wall) {
                Some(t) => {
                    return Some((wall.at(t) - self.pos).project(face_vec).get_length());
                }
                None => {}
            };
        }
        None
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: &LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<commit_msg>Fixed rays intersecting in random order<commit_after>
use std::num::Float;
use sdl::video::{Surface};
use sdl::event::{Key};

use map::{Map};
use math::{LineSeg, Vec2, Mat3};
use input::{InputState};

pub struct Game<'a> {
    pub pos: Vec2,
    pub face_angle: f32,
    pub map: &'a Map,
    pub show_map: bool,
}

impl<'a> Game<'a> {
    pub fn step(&mut self, input: &InputState) {
        if input.has_key(Key::Left) {
            self.face_angle -= 0.02;
        }
        if input.has_key(Key::Right) {
            self.face_angle += 0.02;
        }
        if input.has_key(Key::Up) {
            self.pos.x += Float::sin(self.face_angle);
            self.pos.y -= Float::cos(self.face_angle);
        }
        if input.has_key(Key::Down) {
            self.pos.x -= Float::sin(self.face_angle);
            self.pos.y += Float::cos(self.face_angle);
        }
        self.show_map = input.has_key(Key::Tab);
    }

    pub fn render(&self, surf: &Surface) {
        if self.show_map {
            self.render_lines(&surf);
        } else {
            self.render_cast(&surf);
        }
    }

    fn render_lines(&self, surf: &Surface) {
        let trans = Mat3::rotation(-self.face_angle)
                  * Mat3::translation(-self.pos);

        surf.clear();
        for wall in self.map.walls.iter() {
            draw_seg(&surf, &wall.transform(trans), 0xFF, 0x00, 0x00);
        }

        draw_seg(&surf, &LineSeg::new(0.0, 0.0, 0.0, -5.0), 0x00, 0xFF, 0x00);
    }

    fn render_cast(&self, surf: &Surface) {
        let w = surf.get_width() as usize;
        let h = surf.get_height() as usize;

        surf.clear();
        surf.with_lock(|pixels| {
            for x in 0..w {
                let offset = ((x as f32) - (w as f32) / 2.0) / 600.0;
                match self.cast_ray(offset) {
                    Some(dist) => {
                        let ray_height = (3000.0 / dist) as usize;
                        let top = if h > ray_height { (h - ray_height) / 2 } else { 0 };
                        let bottom = h - top;
                        let proto_color = (0xFF-(h/2) + ray_height/2);
                        let color = if proto_color > 0xFF { 0xFF } else { proto_color as u8 };
                        for y in 0..top {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in top..bottom {
                            put_px(pixels, w, x, y, color, 0, 0);
                        }
                        for y in bottom..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                    None => {
                        for y in 0..(h/2) {
                            put_px(pixels, w, x, y, 0, 0x66, 0xFF);
                        }
                        for y in (h/2)..h {
                            put_px(pixels, w, x, y, 0, 0xBB, 0);
                        }
                    }
                }
            }
            true
        });
    }

    fn cast_ray(&self, offset: f32) -> Option<f32> {
        let ray = LineSeg::new(
            self.pos.x,
            self.pos.y,
            self.pos.x + 1000.0*Float::sin(self.face_angle + offset),
            self.pos.y - 1000.0*Float::cos(self.face_angle + offset)
        );

        let face_vec = Vec2::new(
             Float::sin(self.face_angle),
            -Float::cos(self.face_angle)
        );

        let mut shortest: Option<f32> = None;

        for wall in self.map.walls.iter() {
            match ray.intersects_at(*wall) {
                Some(t) => {
                    let dist = (wall.at(t) - self.pos).project(face_vec).get_length();
                    shortest = match shortest {
                        Some(d) => { if dist < d { Some(dist) } else { shortest } }
                        None    => { Some(dist) }
                    }
                }
                None => {}
            };
        }

        shortest
    }
}

fn put_px(pixels: &mut [u8], w: usize, x: usize, y: usize, r: u8, g: u8, b: u8) {
    pixels[3*(w*y+x) + 0] = b;
    pixels[3*(w*y+x) + 1] = g;
    pixels[3*(w*y+x) + 2] = r;
}

fn draw_seg(surf: &Surface, seg: &LineSeg, r: u8, g: u8, b: u8) {
    let w = surf.get_width() as usize;
    let h = surf.get_height() as usize;
    let len = seg.get_length();

    surf.with_lock(|pixels| {
        for t in 0..(len as usize) {
            let pt = seg.at(t as f32 / len);
            let ux = (pt.x + (w/2) as f32) as usize;
            let uy = (pt.y + (h/2) as f32) as usize;

            if ux < w && uy < h {
                put_px(pixels, w, ux, uy, r, g, b);
            }
        };
        true
    });
}
<|endoftext|>


<commit_before>use std::fmt;

use crate::dictionary::CONF_LINE_WORD_MODIFIER__VISIBLE;
const LINE_WIDTH: usize = 20;

#[derive(Debug)]
struct HangmanChar {
    char_: char,
    visible: bool,
}

impl fmt::Display for HangmanChar {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.visible {
            write!(f, "{}", self.char_)
        } else {
            write!(f, "_")
        }
    }
}

pub enum GameState {
    Ongoing,
    Victory,
    Defeat,
}

#[derive(Debug)]
pub struct Game {
    word: Vec<HangmanChar>,
    pub lives: u8,
    pub last_guess: char,
}

impl Game {
    pub fn state(&self) -> GameState {
        if self.lives == 0 {
            GameState::Defeat
        } else if self.word.iter().all(|c| c.visible) {
            GameState::Victory
        } else {
            GameState::Ongoing
        }
    }

    pub fn new(wordstr: &str, l: u8) -> Game {
        // parse wordsstr, filp 'visible' every CONF_LINE_WORD_MODIFIER__VISIBLE
        let w = wordstr
            .chars()
            // for every * found flip v_acc
            .scan(false, |v_acc, c| {
                *v_acc = *v_acc ^ (c == CONF_LINE_WORD_MODIFIER__VISIBLE);
                Some((c, *v_acc))
            })
            // omit *, we do not need them any more
            .filter(|&(c, _)| c != CONF_LINE_WORD_MODIFIER__VISIBLE)
            // construct objects
            .map(|(c, v)| HangmanChar {
                char_: c,
                visible: v,
            })
            //.inspect(|ref x| println!("after scan:\t{:?}", x))
            .collect();
        Game {
            word: w,
            lives: l,
            last_guess: ' ',
        }
    }

    pub fn guess(&mut self, char_: char) {
        if char_ == '\n' {
            return;
        };
        self.last_guess = char_;
        let mut found = false;
        for h_char in self.word.iter_mut() {
            if h_char.char_.eq_ignore_ascii_case(&char_) {
                h_char.visible = true;
                found = true;
            }
        }

        if !found {
            self.lives -= 1;
        }

        if self.lives == 0 {
            for hc in self.word.iter_mut() {
                hc.visible = true;
            }
        }
    }

    pub fn visible_chars(&self) -> usize {
        self.word.iter().filter(|hc| !hc.visible).count()
    }
}

impl fmt::Display for Game {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        writeln!(
            f,
            "\x1b[KLives:\t{}\tLast guess: {}\n",
            self.lives, self.last_guess
        )?;

        let mut linebreak = false;
        for (n, c) in self.word.iter().enumerate() {
            if n % LINE_WIDTH == 0 {
                linebreak = true
            };
            if n == 0 {
                linebreak = false
            };
            if linebreak && (c.char_ == ' ') {
                linebreak = false;
                write!(f, " {}\n", c)?
            } else {
                write!(f, " {}", c)?
            }
        }
        writeln!(f, "")
    }
}
<commit_msg>use writeln!<commit_after>use std::fmt;

use crate::dictionary::CONF_LINE_WORD_MODIFIER__VISIBLE;
const LINE_WIDTH: usize = 20;

#[derive(Debug)]
struct HangmanChar {
    char_: char,
    visible: bool,
}

impl fmt::Display for HangmanChar {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.visible {
            write!(f, "{}", self.char_)
        } else {
            write!(f, "_")
        }
    }
}

pub enum GameState {
    Ongoing,
    Victory,
    Defeat,
}

#[derive(Debug)]
pub struct Game {
    word: Vec<HangmanChar>,
    pub lives: u8,
    pub last_guess: char,
}

impl Game {
    pub fn state(&self) -> GameState {
        if self.lives == 0 {
            GameState::Defeat
        } else if self.word.iter().all(|c| c.visible) {
            GameState::Victory
        } else {
            GameState::Ongoing
        }
    }

    pub fn new(wordstr: &str, l: u8) -> Game {
        // parse wordsstr, filp 'visible' every CONF_LINE_WORD_MODIFIER__VISIBLE
        let w = wordstr
            .chars()
            // for every * found flip v_acc
            .scan(false, |v_acc, c| {
                *v_acc = *v_acc ^ (c == CONF_LINE_WORD_MODIFIER__VISIBLE);
                Some((c, *v_acc))
            })
            // omit *, we do not need them any more
            .filter(|&(c, _)| c != CONF_LINE_WORD_MODIFIER__VISIBLE)
            // construct objects
            .map(|(c, v)| HangmanChar {
                char_: c,
                visible: v,
            })
            //.inspect(|ref x| println!("after scan:\t{:?}", x))
            .collect();
        Game {
            word: w,
            lives: l,
            last_guess: ' ',
        }
    }

    pub fn guess(&mut self, char_: char) {
        if char_ == '\n' {
            return;
        };
        self.last_guess = char_;
        let mut found = false;
        for h_char in self.word.iter_mut() {
            if h_char.char_.eq_ignore_ascii_case(&char_) {
                h_char.visible = true;
                found = true;
            }
        }

        if !found {
            self.lives -= 1;
        }

        if self.lives == 0 {
            for hc in self.word.iter_mut() {
                hc.visible = true;
            }
        }
    }

    pub fn visible_chars(&self) -> usize {
        self.word.iter().filter(|hc| !hc.visible).count()
    }
}

impl fmt::Display for Game {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        writeln!(
            f,
            "\x1b[KLives:\t{}\tLast guess: {}\n",
            self.lives, self.last_guess
        )?;

        let mut linebreak = false;
        for (n, c) in self.word.iter().enumerate() {
            if n % LINE_WIDTH == 0 {
                linebreak = true
            };
            if n == 0 {
                linebreak = false
            };
            if linebreak && (c.char_ == ' ') {
                linebreak = false;
                writeln!(f, " {}", c)?
            } else {
                write!(f, " {}", c)?
            }
        }
        writeln!(f)
    }
}
<|endoftext|>