<commit_before>//! This module is an attempt at rustifying the OSStatus result.

use bindings::audio_unit::OSStatus;
pub use self::audio::Error as AudioError;
pub use self::audio_codec::Error as AudioCodecError;
pub use self::audio_unit::Error as AudioUnitError;

pub mod audio {
    use bindings::audio_unit::OSStatus;

    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        Unimplemented    = -4,
        FileNotFound     = -43,
        FilePermission   = -54,
        TooManyFilesOpen = -42,
        BadFilePath      = 561017960,
        Param            = -50,
        MemFull          = -108,
        Unknown,
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                0         => Ok(()),
                -4        => Err(Error::Unimplemented),
                -43       => Err(Error::FileNotFound),
                -54       => Err(Error::FilePermission),
                -42       => Err(Error::TooManyFilesOpen),
                561017960 => Err(Error::BadFilePath),
                -50       => Err(Error::Param),
                -108      => Err(Error::MemFull),
                _         => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Unimplemented    => "Unimplemented",
                Error::FileNotFound     => "File not found",
                Error::FilePermission   => "File permission",
                Error::TooManyFilesOpen => "Too many files open",
                Error::BadFilePath      => "Bad file path",
                Error::Param            => "Param",
                Error::MemFull          => "Memory full",
                Error::Unknown          => "An unknown error occurred",
            }
        }
    }

}

pub mod audio_codec {
    use bindings::audio_unit::OSStatus;

    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        Unspecified          = 2003329396,
        UnknownProperty      = 2003332927,
        BadPropertySize      = 561211770,
        IllegalOperation     = 1852797029,
        UnsupportedFormat    = 560226676,
        State                = 561214580,
        NotEnoughBufferSpace = 560100710,
        Unknown,
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                0          => Ok(()),
                2003329396 => Err(Error::Unspecified),
                2003332927 => Err(Error::UnknownProperty),
                561211770  => Err(Error::BadPropertySize),
                1852797029 => Err(Error::IllegalOperation),
                560226676  => Err(Error::UnsupportedFormat),
                561214580  => Err(Error::State),
                560100710  => Err(Error::NotEnoughBufferSpace),
                _          => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Unspecified          => "Unspecified",
                Error::UnknownProperty      => "Unknown property",
                Error::BadPropertySize      => "Bad property size",
                Error::IllegalOperation     => "Illegal operation",
                Error::UnsupportedFormat    => "Unsupported format",
                Error::State                => "State",
                Error::NotEnoughBufferSpace => "Not enough buffer space",
                Error::Unknown              => "Unknown error occurred",
            }
        }
    }

}

pub mod audio_unit {
    use bindings::audio_unit::OSStatus;

    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        InvalidProperty          = -10879,
        InvalidParameter         = -10878,
        InvalidElement           = -10877,
        NoConnection             = -10876,
        FailedInitialization     = -10875,
        TooManyFramesToProcess   = -10874,
        InvalidFile              = -10871,
        FormatNotSupported       = -10868,
        Uninitialized            = -10867,
        InvalidScope             = -10866,
        PropertyNotWritable      = -10865,
        CannotDoInCurrentContext = -10863,
        InvalidPropertyValue     = -10851,
        PropertyNotInUse         = -10850,
        Initialized              = -10849,
        InvalidOfflineRender     = -10848,
        Unauthorized             = -10847,
        Unknown,
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                -10879 => Err(Error::InvalidProperty),
                -10878 => Err(Error::InvalidParameter),
                -10877 => Err(Error::InvalidElement),
                -10876 => Err(Error::NoConnection),
                -10875 => Err(Error::FailedInitialization),
                -10874 => Err(Error::TooManyFramesToProcess),
                -10871 => Err(Error::InvalidFile),
                -10868 => Err(Error::FormatNotSupported),
                -10867 => Err(Error::Uninitialized),
                -10866 => Err(Error::InvalidScope),
                -10865 => Err(Error::PropertyNotWritable),
                -10863 => Err(Error::CannotDoInCurrentContext),
                -10851 => Err(Error::InvalidPropertyValue),
                -10850 => Err(Error::PropertyNotInUse),
                -10849 => Err(Error::Initialized),
                -10848 => Err(Error::InvalidOfflineRender),
                -10847 => Err(Error::Unauthorized),
                _      => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::InvalidProperty          => "Invalid property",
                Error::InvalidParameter         => "Invalid parameter",
                Error::InvalidElement           => "Invalid element",
                Error::NoConnection             => "No connection",
                Error::FailedInitialization     => "Failed initialization",
                Error::TooManyFramesToProcess   => "Too many frames to process",
                Error::InvalidFile              => "Invalid file",
                Error::FormatNotSupported       => "Format not supported",
                Error::Uninitialized            => "Uninitialized",
                Error::InvalidScope             => "Invalid scope",
                Error::PropertyNotWritable      => "Property not writable",
                Error::CannotDoInCurrentContext => "Cannot do in current context",
                Error::InvalidPropertyValue     => "Invalid property value",
                Error::PropertyNotInUse         => "Property not in use",
                Error::Initialized              => "Initialized",
                Error::InvalidOfflineRender     => "Invalid offline render",
                Error::Unauthorized             => "Unauthorized",
                Error::Unknown                  => "Unknown error occurred",
            }
        }
    }

}

/// A wrapper around all possible Core Audio errors.
#[derive(Copy, Clone, Debug)]
pub enum Error {
    Unspecified,
    SystemSoundClientMessageTimedOut,
    NoMatchingDefaultAudioUnitFound,
    RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat,
    NoKnownSubtype,
    Audio(AudioError),
    AudioCodec(AudioCodecError),
    AudioUnit(AudioUnitError),
    Unknown,
}

impl Error {

    /// Convert an OSStatus to a std Rust Result.
    pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
        match os_status {
            0     => Ok(()),
            -1500 => Err(Error::Unspecified),
            -1501 => Err(Error::SystemSoundClientMessageTimedOut),
            _     => {
                match AudioError::from_os_status(os_status) {
                    Ok(())                   => return Ok(()),
                    Err(AudioError::Unknown) => (),
                    Err(err)                 => return Err(Error::Audio(err)),
                }
                match AudioCodecError::from_os_status(os_status) {
                    Ok(())                        => return Ok(()),
                    Err(AudioCodecError::Unknown) => (),
                    Err(err)                      => return Err(Error::AudioCodec(err)),
                }
                match AudioUnitError::from_os_status(os_status) {
                    Ok(())                       => return Ok(()),
                    Err(AudioUnitError::Unknown) => (),
                    Err(err)                     => return Err(Error::AudioUnit(err)),
                }
                Err(Error::Unknown)
            },
        }
    }

    /// Convert an Error to an OSStatus.
    pub fn to_os_status(&self) -> OSStatus {
        match *self {
            Error::Unspecified                                                 => -1500,
            Error::NoMatchingDefaultAudioUnitFound                             => -1500,
            Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat => -1500,
            Error::SystemSoundClientMessageTimedOut                            => -1501,
            Error::Audio(err)                                                  => err as OSStatus,
            Error::AudioCodec(err)                                             => err as OSStatus,
            Error::AudioUnit(err)                                              => err as OSStatus,
            _                                                                  => -1500,
        }
    }

}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        write!(f, "{:?}", self)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Unspecified                      => "An unspecified error has occurred",
            Error::NoMatchingDefaultAudioUnitFound  => "No matching default audio unit found",
            Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat =>
                "The given render callback buffer format does not match the `AudioUnit` `StreamFormat`",
            Error::SystemSoundClientMessageTimedOut => "The system sound client message timed out",
            Error::NoKnownSubtype                   => "The type has no known subtypes",
            Error::Audio(ref err)                   => err.description(),
            Error::AudioCodec(ref err)              => err.description(),
            Error::AudioUnit(ref err)               => err.description(),
            Error::Unknown                          => "An unknown error occurred",
        }
    }
}

<commit_msg>Begin adding support for AudioFormat error codes<commit_after>//! This module is an attempt at rustifying the OSStatus result.

use bindings::audio_unit::OSStatus;
pub use self::audio::Error as AudioError;
pub use self::audio_codec::Error as AudioCodecError;
pub use self::audio_format::Error as AudioFormatError;
pub use self::audio_unit::Error as AudioUnitError;

pub mod audio {
    use bindings::audio_unit::OSStatus;

    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        Unimplemented    = -4,
        FileNotFound     = -43,
        FilePermission   = -54,
        TooManyFilesOpen = -42,
        BadFilePath      = 561017960,
        Param            = -50,
        MemFull          = -108,
        Unknown,
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                0         => Ok(()),
                -4        => Err(Error::Unimplemented),
                -43       => Err(Error::FileNotFound),
                -54       => Err(Error::FilePermission),
                -42       => Err(Error::TooManyFilesOpen),
                561017960 => Err(Error::BadFilePath),
                -50       => Err(Error::Param),
                -108      => Err(Error::MemFull),
                _         => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Unimplemented    => "Unimplemented",
                Error::FileNotFound     => "File not found",
                Error::FilePermission   => "File permission",
                Error::TooManyFilesOpen => "Too many files open",
                Error::BadFilePath      => "Bad file path",
                Error::Param            => "Param",
                Error::MemFull          => "Memory full",
                Error::Unknown          => "An unknown error occurred",
            }
        }
    }

}

pub mod audio_codec {
    use bindings::audio_unit::OSStatus;

    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        Unspecified          = 2003329396,
        UnknownProperty      = 2003332927,
        BadPropertySize      = 561211770,
        IllegalOperation     = 1852797029,
        UnsupportedFormat    = 560226676,
        State                = 561214580,
        NotEnoughBufferSpace = 560100710,
        Unknown,
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                0          => Ok(()),
                2003329396 => Err(Error::Unspecified),
                2003332927 => Err(Error::UnknownProperty),
                561211770  => Err(Error::BadPropertySize),
                1852797029 => Err(Error::IllegalOperation),
                560226676  => Err(Error::UnsupportedFormat),
                561214580  => Err(Error::State),
                560100710  => Err(Error::NotEnoughBufferSpace),
                _          => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Unspecified          => "Unspecified",
                Error::UnknownProperty      => "Unknown property",
                Error::BadPropertySize      => "Bad property size",
                Error::IllegalOperation     => "Illegal operation",
                Error::UnsupportedFormat    => "Unsupported format",
                Error::State                => "State",
                Error::NotEnoughBufferSpace => "Not enough buffer space",
                Error::Unknown              => "Unknown error occurred",
            }
        }
    }

}

pub mod audio_format {
    use bindings::audio_unit::OSStatus;

    // TODO: Finish implementing these values.
    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        Unspecified, // 'what'
        UnsupportedProperty, // 'prop'
        BadPropertySize, // '!siz'
        BadSpecifierSize, // '!spc'
        UnsupportedDataFormat = 1718449215, // 'fmt?'
        UnknownFormat, // '!fmt'
        Unknown, //
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                0          => Ok(()),
                1718449215 => Err(Error::UnsupportedDataFormat),
                _ => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Unspecified           => "An unspecified error",
                Error::UnsupportedProperty   => "The specified property is not supported",
                Error::BadPropertySize       => "Bad property size",
                Error::BadSpecifierSize      => "Bad specifier size",
                Error::UnsupportedDataFormat => "The specified data format is not supported",
                Error::UnknownFormat         => "The specified data format is not a known format",
                Error::Unknown               => "Unknown error occurred",
            }
        }
    }
}

pub mod audio_unit {
    use bindings::audio_unit::OSStatus;

    #[derive(Copy, Clone, Debug)]
    pub enum Error {
        InvalidProperty          = -10879,
        InvalidParameter         = -10878,
        InvalidElement           = -10877,
        NoConnection             = -10876,
        FailedInitialization     = -10875,
        TooManyFramesToProcess   = -10874,
        InvalidFile              = -10871,
        FormatNotSupported       = -10868,
        Uninitialized            = -10867,
        InvalidScope             = -10866,
        PropertyNotWritable      = -10865,
        CannotDoInCurrentContext = -10863,
        InvalidPropertyValue     = -10851,
        PropertyNotInUse         = -10850,
        Initialized              = -10849,
        InvalidOfflineRender     = -10848,
        Unauthorized             = -10847,
        Unknown,
    }

    impl Error {

        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
            match os_status {
                -10879 => Err(Error::InvalidProperty),
                -10878 => Err(Error::InvalidParameter),
                -10877 => Err(Error::InvalidElement),
                -10876 => Err(Error::NoConnection),
                -10875 => Err(Error::FailedInitialization),
                -10874 => Err(Error::TooManyFramesToProcess),
                -10871 => Err(Error::InvalidFile),
                -10868 => Err(Error::FormatNotSupported),
                -10867 => Err(Error::Uninitialized),
                -10866 => Err(Error::InvalidScope),
                -10865 => Err(Error::PropertyNotWritable),
                -10863 => Err(Error::CannotDoInCurrentContext),
                -10851 => Err(Error::InvalidPropertyValue),
                -10850 => Err(Error::PropertyNotInUse),
                -10849 => Err(Error::Initialized),
                -10848 => Err(Error::InvalidOfflineRender),
                -10847 => Err(Error::Unauthorized),
                _      => Err(Error::Unknown),
            }
        }

        pub fn to_os_status(&self) -> OSStatus {
            *self as OSStatus
        }

    }

    impl ::std::fmt::Display for Error {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
            write!(f, "{:?}", self)
        }
    }

    impl ::std::error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::InvalidProperty          => "Invalid property",
                Error::InvalidParameter         => "Invalid parameter",
                Error::InvalidElement           => "Invalid element",
                Error::NoConnection             => "No connection",
                Error::FailedInitialization     => "Failed initialization",
                Error::TooManyFramesToProcess   => "Too many frames to process",
                Error::InvalidFile              => "Invalid file",
                Error::FormatNotSupported       => "Format not supported",
                Error::Uninitialized            => "Uninitialized",
                Error::InvalidScope             => "Invalid scope",
                Error::PropertyNotWritable      => "Property not writable",
                Error::CannotDoInCurrentContext => "Cannot do in current context",
                Error::InvalidPropertyValue     => "Invalid property value",
                Error::PropertyNotInUse         => "Property not in use",
                Error::Initialized              => "Initialized",
                Error::InvalidOfflineRender     => "Invalid offline render",
                Error::Unauthorized             => "Unauthorized",
                Error::Unknown                  => "Unknown error occurred",
            }
        }
    }

}

/// A wrapper around all possible Core Audio errors.
#[derive(Copy, Clone, Debug)]
pub enum Error {
    Unspecified,
    SystemSoundClientMessageTimedOut,
    NoMatchingDefaultAudioUnitFound,
    RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat,
    NoKnownSubtype,
    Audio(AudioError),
    AudioCodec(AudioCodecError),
    AudioFormat(AudioFormatError),
    AudioUnit(AudioUnitError),
    Unknown(OSStatus),
}

impl Error {

    /// Convert an OSStatus to a std Rust Result.
    pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
        match os_status {
            0     => Ok(()),
            -1500 => Err(Error::Unspecified),
            -1501 => Err(Error::SystemSoundClientMessageTimedOut),
            _     => {
                match AudioError::from_os_status(os_status) {
                    Ok(())                   => return Ok(()),
                    Err(AudioError::Unknown) => (),
                    Err(err)                 => return Err(Error::Audio(err)),
                }
                match AudioCodecError::from_os_status(os_status) {
                    Ok(())                        => return Ok(()),
                    Err(AudioCodecError::Unknown) => (),
                    Err(err)                      => return Err(Error::AudioCodec(err)),
                }
                match AudioFormatError::from_os_status(os_status) {
                    Ok(()) => return Ok(()),
                    Err(AudioFormatError::Unknown) => (),
                    Err(err) => return Err(Error::AudioFormat(err)),
                }
                match AudioUnitError::from_os_status(os_status) {
                    Ok(())                       => return Ok(()),
                    Err(AudioUnitError::Unknown) => (),
                    Err(err)                     => return Err(Error::AudioUnit(err)),
                }
                Err(Error::Unknown(os_status))
            },
        }
    }

    /// Convert an Error to an OSStatus.
    pub fn to_os_status(&self) -> OSStatus {
        match *self {
            Error::Unspecified                                                 => -1500,
            Error::NoMatchingDefaultAudioUnitFound                             => -1500,
            Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat => -1500,
            Error::SystemSoundClientMessageTimedOut                            => -1501,
            Error::Audio(err)                                                  => err as OSStatus,
            Error::AudioCodec(err)                                             => err as OSStatus,
            Error::AudioUnit(err)                                              => err as OSStatus,
            _                                                                  => -1500,
        }
    }

}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
        write!(f, "{:?}", self)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Unspecified                      => "An unspecified error has occurred",
            Error::NoMatchingDefaultAudioUnitFound  => "No matching default audio unit found",
            Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat =>
                "The given render callback buffer format does not match the `AudioUnit` `StreamFormat`",
            Error::SystemSoundClientMessageTimedOut => "The system sound client message timed out",
            Error::NoKnownSubtype                   => "The type has no known subtypes",
            Error::Audio(ref err)                   => err.description(),
            Error::AudioCodec(ref err)              => err.description(),
            Error::AudioFormat(ref err)             => err.description(),
            Error::AudioUnit(ref err)               => err.description(),
            Error::Unknown(_)                       => "An unknown error unknown to the coreaudio-rs API occurred",
        }
    }
}

<|endoftext|>


<commit_before>//! User-input events and their effects.
//!
//! * Every user input the application receives is converted to an
//!   [`Event`](./enum.Event.html).
//! * Each event is then given to the root, and descends the view tree down to
//!   the view currently in focus, through the
//!   [`on_event`](../view/trait.View.html#method.on_event) method.
//!     * If the view consumes the event, it may return a callback to be
//!       executed.
//!     * Otherwise, it ignores the event, and the view parent can in turn
//!       choose to consume it or not.
//! * If no view consumes the event, the
//!   [global callback](../struct.Cursive.html#method.add_global_callback)
//!   table is checked.

use std::any::Any;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use vec::Vec2;
use Cursive;

/// Callback is a function that can be triggered by an event.
/// It has a mutable access to the cursive root.
#[derive(Clone)]
pub struct Callback(Rc<Box<Fn(&mut Cursive)>>);
// TODO: remove the Box when Box<T: Sized> -> Rc<T> is possible

/// A boxed callback that can be run on `&mut Any`.
pub type AnyCb<'a> = Box<FnMut(&mut Any) + 'a>;

/// A trigger that only selects some types of events.
pub struct EventTrigger(Box<Fn(&Event) -> bool>);

impl EventTrigger {
    /// Create a new `EventTrigger` using the given function as filter.
    pub fn from_fn<F>(f: F) -> Self
    where
        F: 'static + Fn(&Event) -> bool,
    {
        EventTrigger(Box::new(f))
    }

    /// Checks if this trigger applies to the given `Event`.
    pub fn apply(&self, event: &Event) -> bool {
        (self.0)(event)
    }

    /// Returns an `EventTrigger` that only accepts arrow keys.
    ///
    /// Only bare arrow keys without modifiers (Shift, Ctrl, Alt) will be accepted.
    pub fn arrows() -> Self {
        Self::from_fn(|e| match e {
            Event::Key(Key::Left)
            | Event::Key(Key::Down)
            | Event::Key(Key::Up)
            | Event::Key(Key::Right) => true,
            _ => false,
        })
    }

    /// Returns an `EventTrigger` that only accepts mouse events.
    pub fn mouse() -> Self {
        Self::from_fn(|e| match e {
            Event::Mouse { .. } => true,
            _ => false,
        })
    }

    /// Returns an `EventTrigger` that accepts any event.
    pub fn any() -> Self {
        Self::from_fn(|_| true)
    }

    /// Returns an `EventTrigger` that doesn't accept any event.
    pub fn none() -> Self {
        Self::from_fn(|_| true)
    }

    /// Returns an `EventTrigger` that applies if either `self` or `other` applies.
    pub fn or<O>(self, other: O) -> Self
    where
        O: Into<EventTrigger>,
    {
        let other = other.into();
        Self::from_fn(move |e| self.apply(e) || other.apply(e))
    }
}

impl From<Event> for EventTrigger {
    fn from(event: Event) -> Self {
        Self::from_fn(move |e| *e == event)
    }
}

impl From<char> for EventTrigger {
    fn from(c: char) -> Self {
        Self::from(Event::from(c))
    }
}

impl From<Key> for EventTrigger {
    fn from(k: Key) -> Self {
        Self::from(Event::from(k))
    }
}

impl<F> From<F> for EventTrigger
where
    F: 'static + Fn(&Event) -> bool,
{
    fn from(f: F) -> Self {
        Self::from_fn(f)
    }
}

impl Callback {
    /// Wraps the given function into a `Callback` object.
    pub fn from_fn<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        Callback(Rc::new(Box::new(move |siv| {
            f(siv);
        })))
    }

    /// Wrap a `FnMut` into a `Callback` object.
    ///
    /// If this methods tries to call itself, nested calls will be no-ops.
    pub fn from_fn_mut<F>(f: F) -> Self
    where
        F: 'static + FnMut(&mut Cursive),
    {
        let cb = RefCell::new(f);

        Self::from_fn(move |s| {
            if let Ok(mut cb) = cb.try_borrow_mut() {
                (&mut *cb)(s);
            }
        })
    }

    /// Returns a dummy callback that doesn't run anything.
    pub fn dummy() -> Self {
        Callback::from_fn(|_| ())
    }
}

impl Deref for Callback {
    type Target = Box<Fn(&mut Cursive)>;
    fn deref<'a>(&'a self) -> &'a Box<Fn(&mut Cursive)> {
        &self.0
    }
}

impl From<Rc<Box<Fn(&mut Cursive)>>> for Callback {
    fn from(f: Rc<Box<Fn(&mut Cursive)>>) -> Self {
        Callback(f)
    }
}

impl From<Box<Fn(&mut Cursive) + Send>> for Callback {
    fn from(f: Box<Fn(&mut Cursive) + Send>) -> Self {
        Callback(Rc::new(f))
    }
}

impl From<Box<Fn(&mut Cursive)>> for Callback {
    fn from(f: Box<Fn(&mut Cursive)>) -> Self {
        Callback(Rc::new(f))
    }
}

/// Answer to an event notification.
/// The event can be consumed or ignored.
pub enum EventResult {
    /// The event was ignored. The parent can keep handling it.
    Ignored,
    /// The event was consumed. An optionnal callback to run is attached.
    Consumed(Option<Callback>), // TODO: make this a FnOnce?
}

impl EventResult {
    /// Convenient method to create `Consumed(Some(f))`
    pub fn with_cb<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        EventResult::Consumed(Some(Callback::from_fn(f)))
    }

    /// Returns `true` if `self` is `EventResult::Consumed`.
    pub fn is_consumed(&self) -> bool {
        match *self {
            EventResult::Consumed(_) => true,
            _ => false,
        }
    }

    /// Returns `true` if `self` contains a callback.
    pub fn has_callback(&self) -> bool {
        match *self {
            EventResult::Consumed(Some(_)) => true,
            _ => false,
        }
    }

    /// Process this result if it is a callback.
    ///
    /// Does nothing otherwise.
    pub fn process(self, s: &mut Cursive) {
        if let EventResult::Consumed(Some(cb)) = self {
            cb(s);
        }
    }

    /// Returns `self` if it is not `EventResult::Ignored`, otherwise returns `f()`.
    pub fn or_else<F>(self, f: F) -> Self
    where
        F: FnOnce() -> EventResult,
    {
        match self {
            EventResult::Ignored => f(),
            other => other,
        }
    }

    /// Returns an event result that combines `self` and `other`.
    pub fn and(self, other: Self) -> Self {
        match (self, other) {
            (EventResult::Ignored, result)
            | (result, EventResult::Ignored) => result,
            (EventResult::Consumed(None), EventResult::Consumed(cb))
            | (EventResult::Consumed(cb), EventResult::Consumed(None)) => {
                EventResult::Consumed(cb)
            }
            (
                EventResult::Consumed(Some(cb1)),
                EventResult::Consumed(Some(cb2)),
            ) => EventResult::with_cb(move |siv| {
                (cb1)(siv);
                (cb2)(siv);
            }),
        }
    }
}

/// A non-character key on the keyboard
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum Key {
    /// Both Enter (or Return) and numpad Enter
    Enter,
    /// Tabulation key
    Tab,
    /// Backspace key
    Backspace,
    /// Escape key
    Esc,

    /// Left arrow
    Left,
    /// Right arrow
    Right,
    /// Up arrow
    Up,
    /// Down arrow
    Down,

    /// Insert key
    Ins,
    /// Delete key
    Del,
    /// Home key
    Home,
    /// End key
    End,
    /// Page Up key
    PageUp,
    /// Page Down key
    PageDown,

    /// Pause Break key
    PauseBreak,

    /// The 5 in the center of the keypad, when numlock is disabled.
    NumpadCenter,

    /// F0 key
    F0,
    /// F1 key
    F1,
    /// F2 key
    F2,
    /// F3 key
    F3,
    /// F4 key
    F4,
    /// F5 key
    F5,
    /// F6 key
    F6,
    /// F7 key
    F7,
    /// F8 key
    F8,
    /// F9 key
    F9,
    /// F10 key
    F10,
    /// F11 key
    F11,
    /// F12 key
    F12,
}

impl Key {
    /// Returns the function key corresponding to the given number
    ///
    /// 1 -> F1, etc...
    ///
    /// # Panics
    ///
    /// If `n == 0 || n > 12`
    pub fn from_f(n: u8) -> Key {
        match n {
            0 => Key::F0,
            1 => Key::F1,
            2 => Key::F2,
            3 => Key::F3,
            4 => Key::F4,
            5 => Key::F5,
            6 => Key::F6,
            7 => Key::F7,
            8 => Key::F8,
            9 => Key::F9,
            10 => Key::F10,
            11 => Key::F11,
            12 => Key::F12,
            _ => panic!("unknown function key: F{}", n),
        }
    }
}

/// One of the buttons present on the mouse
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseButton {
    /// The left button, used for main actions.
    Left,
    /// Middle button, probably the wheel. Often pastes text in X11 on linux.
    Middle,
    /// The right button, for special actions.
    Right,

    /// Fourth button if the mouse supports it.
    Button4,
    /// Fifth button if the mouse supports it.
    Button5,

    // TODO: handle more buttons?
    #[doc(hidden)]
    Other,
}

/// Represents a possible event sent by the mouse.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseEvent {
    /// A button was pressed.
    Press(MouseButton),
    /// A button was released.
    Release(MouseButton),
    /// A button is being held.
    Hold(MouseButton),
    /// The wheel was moved up.
    WheelUp,
    /// The wheel was moved down.
    WheelDown,
}

impl MouseEvent {
    /// Returns the button used by this event, if any.
    ///
    /// Returns `None` if `self` is `WheelUp` or `WheelDown`.
    pub fn button(self) -> Option<MouseButton> {
        match self {
            MouseEvent::Press(btn)
            | MouseEvent::Release(btn)
            | MouseEvent::Hold(btn) => Some(btn),
            _ => None,
        }
    }

    /// Returns `true` if `self` is an event that can grab focus.
    ///
    /// This includes `Press`, `WheelUp` and `WheelDown`.
    pub fn grabs_focus(self) -> bool {
        match self {
            MouseEvent::Press(_)
            | MouseEvent::WheelUp
            | MouseEvent::WheelDown => true,
            _ => false,
        }
    }
}

/// Represents an event as seen by the application.
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Event {
    /// Event fired when the window is resized.
    WindowResize,

    /// Event fired regularly when a auto-refresh is set.
    Refresh,

    // TODO: have Char(modifier, char) and Key(modifier, key) enums?
    /// A character was entered (includes numbers, punctuation, ...).
    Char(char),
    /// A character was entered with the Ctrl key pressed.
    CtrlChar(char),
    /// A character was entered with the Alt key pressed.
    AltChar(char),

    /// A non-character key was pressed.
    Key(Key),
    /// A non-character key was pressed with the Shift key pressed.
    Shift(Key),
    /// A non-character key was pressed with the Alt key pressed.
    Alt(Key),
    /// A non-character key was pressed with the Shift and Alt keys pressed.
    AltShift(Key),
    /// A non-character key was pressed with the Ctrl key pressed.
    Ctrl(Key),
    /// A non-character key was pressed with the Ctrl and Shift keys pressed.
    CtrlShift(Key),
    /// A non-character key was pressed with the Ctrl and Alt keys pressed.
    CtrlAlt(Key),

    /// A mouse event was sent.
    Mouse {
        /// Position of the top-left corner of the view receiving this event.
        offset: Vec2,
        /// Position of the mouse when this event was fired.
        position: Vec2,
        /// The mouse event itself.
        event: MouseEvent,
    },

    // TODO: use a backend-dependent type for the unknown values?
    /// An unknown event was received.
    Unknown(Vec<u8>),

    // Maybe add a `Custom(Rc<Any>)` ?

    // Having a doc-hidden event prevents people from having exhaustive
    // matches, allowing us to add events in the future.
    #[doc(hidden)]
    /// The application is about to exit.
    Exit,
}

impl Event {
    /// Returns the position of the mouse, if `self` is a mouse event.
    pub fn mouse_position(&self) -> Option<Vec2> {
        if let Event::Mouse { position, .. } = *self {
            Some(position)
        } else {
            None
        }
    }

    /// Returns a mutable reference to the position of the mouse/
    ///
    /// Returns `None` if `self` is not a mouse event.
    pub fn mouse_position_mut(&mut self) -> Option<&mut Vec2> {
        if let Event::Mouse {
            ref mut position, ..
        } = *self
        {
            Some(position)
        } else {
            None
        }
    }

    /// Update `self` with the given offset.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, do nothing.
    pub fn relativize<V>(&mut self, top_left: V)
    where
        V: Into<Vec2>,
    {
        if let Event::Mouse { ref mut offset, .. } = *self {
            *offset = *offset + top_left;
        }
    }

    /// Returns a cloned, relativized event.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, returns a simple clone.
    pub fn relativized<V>(&self, top_left: V) -> Self
    where
        V: Into<Vec2>,
    {
        let mut result = self.clone();
        result.relativize(top_left);
        result
    }
}

impl From<char> for Event {
    fn from(c: char) -> Event {
        Event::Char(c)
    }
}

impl From<Key> for Event {
    fn from(k: Key) -> Event {
        Event::Key(k)
    }
}
<commit_msg>Fix EventTrigger::none<commit_after>//! User-input events and their effects.
//!
//! * Every user input the application receives is converted to an
//!   [`Event`](./enum.Event.html).
//! * Each event is then given to the root, and descends the view tree down to
//!   the view currently in focus, through the
//!   [`on_event`](../view/trait.View.html#method.on_event) method.
//!     * If the view consumes the event, it may return a callback to be
//!       executed.
//!     * Otherwise, it ignores the event, and the view parent can in turn
//!       choose to consume it or not.
//! * If no view consumes the event, the
//!   [global callback](../struct.Cursive.html#method.add_global_callback)
//!   table is checked.

use std::any::Any;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use vec::Vec2;
use Cursive;

/// Callback is a function that can be triggered by an event.
/// It has a mutable access to the cursive root.
#[derive(Clone)]
pub struct Callback(Rc<Box<Fn(&mut Cursive)>>);
// TODO: remove the Box when Box<T: Sized> -> Rc<T> is possible

/// A boxed callback that can be run on `&mut Any`.
pub type AnyCb<'a> = Box<FnMut(&mut Any) + 'a>;

/// A trigger that only selects some types of events.
pub struct EventTrigger(Box<Fn(&Event) -> bool>);

impl EventTrigger {
    /// Create a new `EventTrigger` using the given function as filter.
    pub fn from_fn<F>(f: F) -> Self
    where
        F: 'static + Fn(&Event) -> bool,
    {
        EventTrigger(Box::new(f))
    }

    /// Checks if this trigger applies to the given `Event`.
    pub fn apply(&self, event: &Event) -> bool {
        (self.0)(event)
    }

    /// Returns an `EventTrigger` that only accepts arrow keys.
    ///
    /// Only bare arrow keys without modifiers (Shift, Ctrl, Alt) will be accepted.
    pub fn arrows() -> Self {
        Self::from_fn(|e| match e {
            Event::Key(Key::Left)
            | Event::Key(Key::Down)
            | Event::Key(Key::Up)
            | Event::Key(Key::Right) => true,
            _ => false,
        })
    }

    /// Returns an `EventTrigger` that only accepts mouse events.
    pub fn mouse() -> Self {
        Self::from_fn(|e| match e {
            Event::Mouse { .. } => true,
            _ => false,
        })
    }

    /// Returns an `EventTrigger` that accepts any event.
    pub fn any() -> Self {
        Self::from_fn(|_| true)
    }

    /// Returns an `EventTrigger` that doesn't accept any event.
    pub fn none() -> Self {
        Self::from_fn(|_| false)
    }

    /// Returns an `EventTrigger` that applies if either `self` or `other` applies.
    pub fn or<O>(self, other: O) -> Self
    where
        O: Into<EventTrigger>,
    {
        let other = other.into();
        Self::from_fn(move |e| self.apply(e) || other.apply(e))
    }
}

impl From<Event> for EventTrigger {
    fn from(event: Event) -> Self {
        Self::from_fn(move |e| *e == event)
    }
}

impl From<char> for EventTrigger {
    fn from(c: char) -> Self {
        Self::from(Event::from(c))
    }
}

impl From<Key> for EventTrigger {
    fn from(k: Key) -> Self {
        Self::from(Event::from(k))
    }
}

impl<F> From<F> for EventTrigger
where
    F: 'static + Fn(&Event) -> bool,
{
    fn from(f: F) -> Self {
        Self::from_fn(f)
    }
}

impl Callback {
    /// Wraps the given function into a `Callback` object.
    pub fn from_fn<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        Callback(Rc::new(Box::new(move |siv| {
            f(siv);
        })))
    }

    /// Wrap a `FnMut` into a `Callback` object.
    ///
    /// If this methods tries to call itself, nested calls will be no-ops.
    pub fn from_fn_mut<F>(f: F) -> Self
    where
        F: 'static + FnMut(&mut Cursive),
    {
        let cb = RefCell::new(f);

        Self::from_fn(move |s| {
            if let Ok(mut cb) = cb.try_borrow_mut() {
                (&mut *cb)(s);
            }
        })
    }

    /// Returns a dummy callback that doesn't run anything.
    pub fn dummy() -> Self {
        Callback::from_fn(|_| ())
    }
}

impl Deref for Callback {
    type Target = Box<Fn(&mut Cursive)>;
    fn deref<'a>(&'a self) -> &'a Box<Fn(&mut Cursive)> {
        &self.0
    }
}

impl From<Rc<Box<Fn(&mut Cursive)>>> for Callback {
    fn from(f: Rc<Box<Fn(&mut Cursive)>>) -> Self {
        Callback(f)
    }
}

impl From<Box<Fn(&mut Cursive) + Send>> for Callback {
    fn from(f: Box<Fn(&mut Cursive) + Send>) -> Self {
        Callback(Rc::new(f))
    }
}

impl From<Box<Fn(&mut Cursive)>> for Callback {
    fn from(f: Box<Fn(&mut Cursive)>) -> Self {
        Callback(Rc::new(f))
    }
}

/// Answer to an event notification.
/// The event can be consumed or ignored.
pub enum EventResult {
    /// The event was ignored. The parent can keep handling it.
    Ignored,
    /// The event was consumed. An optionnal callback to run is attached.
    Consumed(Option<Callback>), // TODO: make this a FnOnce?
}

impl EventResult {
    /// Convenient method to create `Consumed(Some(f))`
    pub fn with_cb<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        EventResult::Consumed(Some(Callback::from_fn(f)))
    }

    /// Returns `true` if `self` is `EventResult::Consumed`.
    pub fn is_consumed(&self) -> bool {
        match *self {
            EventResult::Consumed(_) => true,
            _ => false,
        }
    }

    /// Returns `true` if `self` contains a callback.
    pub fn has_callback(&self) -> bool {
        match *self {
            EventResult::Consumed(Some(_)) => true,
            _ => false,
        }
    }

    /// Process this result if it is a callback.
    ///
    /// Does nothing otherwise.
    pub fn process(self, s: &mut Cursive) {
        if let EventResult::Consumed(Some(cb)) = self {
            cb(s);
        }
    }

    /// Returns `self` if it is not `EventResult::Ignored`, otherwise returns `f()`.
    pub fn or_else<F>(self, f: F) -> Self
    where
        F: FnOnce() -> EventResult,
    {
        match self {
            EventResult::Ignored => f(),
            other => other,
        }
    }

    /// Returns an event result that combines `self` and `other`.
    pub fn and(self, other: Self) -> Self {
        match (self, other) {
            (EventResult::Ignored, result)
            | (result, EventResult::Ignored) => result,
            (EventResult::Consumed(None), EventResult::Consumed(cb))
            | (EventResult::Consumed(cb), EventResult::Consumed(None)) => {
                EventResult::Consumed(cb)
            }
            (
                EventResult::Consumed(Some(cb1)),
                EventResult::Consumed(Some(cb2)),
            ) => EventResult::with_cb(move |siv| {
                (cb1)(siv);
                (cb2)(siv);
            }),
        }
    }
}

/// A non-character key on the keyboard
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum Key {
    /// Both Enter (or Return) and numpad Enter
    Enter,
    /// Tabulation key
    Tab,
    /// Backspace key
    Backspace,
    /// Escape key
    Esc,

    /// Left arrow
    Left,
    /// Right arrow
    Right,
    /// Up arrow
    Up,
    /// Down arrow
    Down,

    /// Insert key
    Ins,
    /// Delete key
    Del,
    /// Home key
    Home,
    /// End key
    End,
    /// Page Up key
    PageUp,
    /// Page Down key
    PageDown,

    /// Pause Break key
    PauseBreak,

    /// The 5 in the center of the keypad, when numlock is disabled.
    NumpadCenter,

    /// F0 key
    F0,
    /// F1 key
    F1,
    /// F2 key
    F2,
    /// F3 key
    F3,
    /// F4 key
    F4,
    /// F5 key
    F5,
    /// F6 key
    F6,
    /// F7 key
    F7,
    /// F8 key
    F8,
    /// F9 key
    F9,
    /// F10 key
    F10,
    /// F11 key
    F11,
    /// F12 key
    F12,
}

impl Key {
    /// Returns the function key corresponding to the given number
    ///
    /// 1 -> F1, etc...
    ///
    /// # Panics
    ///
    /// If `n == 0 || n > 12`
    pub fn from_f(n: u8) -> Key {
        match n {
            0 => Key::F0,
            1 => Key::F1,
            2 => Key::F2,
            3 => Key::F3,
            4 => Key::F4,
            5 => Key::F5,
            6 => Key::F6,
            7 => Key::F7,
            8 => Key::F8,
            9 => Key::F9,
            10 => Key::F10,
            11 => Key::F11,
            12 => Key::F12,
            _ => panic!("unknown function key: F{}", n),
        }
    }
}

/// One of the buttons present on the mouse
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseButton {
    /// The left button, used for main actions.
    Left,
    /// Middle button, probably the wheel. Often pastes text in X11 on linux.
    Middle,
    /// The right button, for special actions.
    Right,

    /// Fourth button if the mouse supports it.
    Button4,
    /// Fifth button if the mouse supports it.
    Button5,

    // TODO: handle more buttons?
    #[doc(hidden)]
    Other,
}

/// Represents a possible event sent by the mouse.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseEvent {
    /// A button was pressed.
    Press(MouseButton),
    /// A button was released.
    Release(MouseButton),
    /// A button is being held.
    Hold(MouseButton),
    /// The wheel was moved up.
    WheelUp,
    /// The wheel was moved down.
    WheelDown,
}

impl MouseEvent {
    /// Returns the button used by this event, if any.
    ///
    /// Returns `None` if `self` is `WheelUp` or `WheelDown`.
    pub fn button(self) -> Option<MouseButton> {
        match self {
            MouseEvent::Press(btn)
            | MouseEvent::Release(btn)
            | MouseEvent::Hold(btn) => Some(btn),
            _ => None,
        }
    }

    /// Returns `true` if `self` is an event that can grab focus.
    ///
    /// This includes `Press`, `WheelUp` and `WheelDown`.
    pub fn grabs_focus(self) -> bool {
        match self {
            MouseEvent::Press(_)
            | MouseEvent::WheelUp
            | MouseEvent::WheelDown => true,
            _ => false,
        }
    }
}

/// Represents an event as seen by the application.
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Event {
    /// Event fired when the window is resized.
    WindowResize,

    /// Event fired regularly when a auto-refresh is set.
    Refresh,

    // TODO: have Char(modifier, char) and Key(modifier, key) enums?
    /// A character was entered (includes numbers, punctuation, ...).
    Char(char),
    /// A character was entered with the Ctrl key pressed.
    CtrlChar(char),
    /// A character was entered with the Alt key pressed.
    AltChar(char),

    /// A non-character key was pressed.
    Key(Key),
    /// A non-character key was pressed with the Shift key pressed.
    Shift(Key),
    /// A non-character key was pressed with the Alt key pressed.
    Alt(Key),
    /// A non-character key was pressed with the Shift and Alt keys pressed.
    AltShift(Key),
    /// A non-character key was pressed with the Ctrl key pressed.
    Ctrl(Key),
    /// A non-character key was pressed with the Ctrl and Shift keys pressed.
    CtrlShift(Key),
    /// A non-character key was pressed with the Ctrl and Alt keys pressed.
    CtrlAlt(Key),

    /// A mouse event was sent.
    Mouse {
        /// Position of the top-left corner of the view receiving this event.
        offset: Vec2,
        /// Position of the mouse when this event was fired.
        position: Vec2,
        /// The mouse event itself.
        event: MouseEvent,
    },

    // TODO: use a backend-dependent type for the unknown values?
    /// An unknown event was received.
    Unknown(Vec<u8>),

    // Maybe add a `Custom(Rc<Any>)` ?

    // Having a doc-hidden event prevents people from having exhaustive
    // matches, allowing us to add events in the future.
    #[doc(hidden)]
    /// The application is about to exit.
    Exit,
}

impl Event {
    /// Returns the position of the mouse, if `self` is a mouse event.
    pub fn mouse_position(&self) -> Option<Vec2> {
        if let Event::Mouse { position, .. } = *self {
            Some(position)
        } else {
            None
        }
    }

    /// Returns a mutable reference to the position of the mouse/
    ///
    /// Returns `None` if `self` is not a mouse event.
    pub fn mouse_position_mut(&mut self) -> Option<&mut Vec2> {
        if let Event::Mouse {
            ref mut position, ..
        } = *self
        {
            Some(position)
        } else {
            None
        }
    }

    /// Update `self` with the given offset.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, do nothing.
    pub fn relativize<V>(&mut self, top_left: V)
    where
        V: Into<Vec2>,
    {
        if let Event::Mouse { ref mut offset, .. } = *self {
            *offset = *offset + top_left;
        }
    }

    /// Returns a cloned, relativized event.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, returns a simple clone.
    pub fn relativized<V>(&self, top_left: V) -> Self
    where
        V: Into<Vec2>,
    {
        let mut result = self.clone();
        result.relativize(top_left);
        result
    }
}

impl From<char> for Event {
    fn from(c: char) -> Event {
        Event::Char(c)
    }
}

impl From<Key> for Event {
    fn from(k: Key) -> Event {
        Event::Key(k)
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate unicode_segmentation;

use std::cmp;
use self::unicode_segmentation::UnicodeSegmentation;
use self::walkdir::WalkDir;

pub fn find_duplicates(dir: &str, expected_dist: usize) {
    let paths = get_paths(dir);
    for i in 0..paths.len() {
        let mut duplicates: Vec<&NamePath> = vec![];
        let ref path1 = paths[i];
        for j in (i + 1)..paths.len() {
            let ref path2 = paths[j];
            let dist = edit_distance(&path1.name, &path2.name);
            if dist <= expected_dist {
                duplicates.push(path2);
            }
        }
        println!("-----------------------------------------------------------------------");
        println!("{} --> {}", path1.name, path1.path);
        println!("-----------------------------------------------------------------------");
        for dupe in duplicates {
            println!("- Duplicate: {} --> {}", dupe.name, dupe.path);
        }
    }
}

fn edit_distance(str1: &str, str2: &str) -> usize {
    let str1_vec = UnicodeSegmentation::graphemes(str1, true).collect::<Vec<&str>>();
    let str2_vec = UnicodeSegmentation::graphemes(str2, true).collect::<Vec<&str>>();
    let str1_size = str1_vec.len() + 1;
    let str2_size = str2_vec.len() + 1;
    let mut dp = vec![vec![0; str2_size]; str1_size];
    for i in 0..str1_size {
        for j in 0..str2_size {
            if i == 0 {
                dp[i][j] = j;
            } else if j == 0 {
                dp[i][j] = i;
            } else if str1_vec[i - 1] == str2_vec[j - 1] {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = 1 + cmp::min(
                    dp[i][j - 1],
                    cmp::min(dp[i - 1][j],
                        dp[i - 1][j - 1]));
            }
        }
    }
    dp[str1_size - 1 as usize][str2_size - 1 as usize]
}

#[derive(Debug)]
struct NamePath {
    name: String,
    path: String,
}

fn get_paths<'a>(dir: &str) -> Vec<NamePath> {
    let mut name_paths: Vec<NamePath> = vec![];
    let walker = WalkDir::new(dir).into_iter();
    for entry in walker.filter_map(|e| e.ok()) {
        let path = entry.path();
        if path.is_file() {
            let name_path = NamePath{
                name: path.file_name().unwrap().to_str().unwrap().to_string(),
                path: path.to_str().unwrap().to_string(),
            };
            name_paths.push(name_path);
        }
    }
    name_paths
}

#[cfg(test)]
mod test {
    use fdupe;
    use std::path::Path;

    #[test]
    fn test_edit_distance() {
        assert_eq!(2, fdupe::edit_distance("hello", "holla"));
        assert_eq!(2, fdupe::edit_distance("hell", "holla"));
        assert_eq!(3, fdupe::edit_distance("abc", "def"));
        assert_eq!(1, fdupe::edit_distance("忠犬ハチ公", "忠犬ハチ"));
        assert_eq!(2, fdupe::edit_distance("犬ハチ公", "忠犬ハチ"));
    }

    #[test]
    fn test_get_paths() {
        assert_eq!(5, fdupe::get_paths(Path::new("src").join("testdata").to_str().unwrap()).len());
    }

    #[test]
    fn test_find_duplicates() {
        fdupe::find_duplicates(Path::new("src").join("testdata").to_str().unwrap(), 2);
    }
}<commit_msg>Update unit test<commit_after>extern crate walkdir;
extern crate unicode_segmentation;

use std::cmp;
use self::unicode_segmentation::UnicodeSegmentation;
use self::walkdir::WalkDir;

pub fn find_duplicates(dir: &str, expected_dist: usize) {
    let paths = get_paths(dir);
    for i in 0..paths.len() {
        let mut duplicates: Vec<&NamePath> = vec![];
        let ref path1 = paths[i];
        for j in (i + 1)..paths.len() {
            let ref path2 = paths[j];
            let dist = edit_distance(&path1.name, &path2.name);
            if dist <= expected_dist {
                duplicates.push(path2);
            }
        }
        println!("-----------------------------------------------------------------------");
        println!("{} --> {}", path1.name, path1.path);
        println!("-----------------------------------------------------------------------");
        for dupe in duplicates {
            println!("- Duplicate: {} --> {}", dupe.name, dupe.path);
        }
    }
}

fn edit_distance(str1: &str, str2: &str) -> usize {
    let str1_vec = UnicodeSegmentation::graphemes(str1, true).collect::<Vec<&str>>();
    let str2_vec = UnicodeSegmentation::graphemes(str2, true).collect::<Vec<&str>>();
    let str1_size = str1_vec.len() + 1;
    let str2_size = str2_vec.len() + 1;
    let mut dp = vec![vec![0; str2_size]; str1_size];
    for i in 0..str1_size {
        for j in 0..str2_size {
            if i == 0 {
                dp[i][j] = j;
            } else if j == 0 {
                dp[i][j] = i;
            } else if str1_vec[i - 1] == str2_vec[j - 1] {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = 1 + cmp::min(
                    dp[i][j - 1],
                    cmp::min(dp[i - 1][j],
                        dp[i - 1][j - 1]));
            }
        }
    }
    dp[str1_size - 1 as usize][str2_size - 1 as usize]
}

#[derive(Debug)]
struct NamePath {
    name: String,
    path: String,
}

fn get_paths<'a>(dir: &str) -> Vec<NamePath> {
    let mut name_paths: Vec<NamePath> = vec![];
    let walker = WalkDir::new(dir).into_iter();
    for entry in walker.filter_map(|e| e.ok()) {
        let path = entry.path();
        if path.is_file() {
            let name_path = NamePath{
                name: path.file_name().unwrap().to_str().unwrap().to_string(),
                path: path.to_str().unwrap().to_string(),
            };
            name_paths.push(name_path);
        }
    }
    name_paths
}

#[cfg(test)]
mod test {
    use fdupe;
    use std::path::Path;

    #[test]
    fn test_edit_distance() {
        assert_eq!(2, fdupe::edit_distance("hello", "holla"));
        assert_eq!(2, fdupe::edit_distance("hell", "holla"));
        assert_eq!(3, fdupe::edit_distance("abc", "def"));
        assert_eq!(1, fdupe::edit_distance("忠犬ハチ公", "忠犬ハチ"));
        assert_eq!(2, fdupe::edit_distance("犬ハチ公", "忠犬ハチ"));
    }

    #[test]
    fn test_get_paths() {
        assert_eq!(5, fdupe::get_paths(Path::new("src").join("testdata").to_str().unwrap()).len());
    }

    #[test]
    fn test_find_duplicates() {
        fdupe::find_duplicates(Path::new("src").join("testdata").to_str().unwrap(), 3);
    }
}<|endoftext|>


<commit_before>extern crate num;

/// The default epsilon value used for floating point comparisons.
pub static EPSILON:f64 = 1.0E-8;

pub trait Float: num::Float{
  /// Tells if the two floating-point values `self` and `y` are considered equal
  /// within the specified `absolute == relative` tolerence value.
  ///
  /// The method of comparison used is described at:
  ///
  /// http://realtimecollisiondetection.net/blog/?p=89
  ///
  /// Also consider using the `equal` method.
  ///
  /// # Examples
  ///
  /// ```
  /// use fiz_math::Float;
  ///
  /// assert!(0.9.almost_equal(1.0, 0.1000001));
  /// assert!(0.9.almost_equal(1.0, 0.1));
  /// ```
  fn almost_equal(self, y: Self, abs_tol: Self) -> bool;

  /// equal is short-hand for `self.almost_equal(y, fiz_math::EPSILON)`.
  ///
  /// # Examples
  ///
  /// ```
  /// use fiz_math::Float;
  ///
  /// assert!(1.00000001.equal(1.0));
  /// assert!(1.0.equal(1.0));
  /// assert!(!0.9.equal(1.0));
  /// ```
  fn equal(self, y: Self) -> bool;
}

impl<T: num::Float> Float for T {
  fn almost_equal(self, y: T, abs_tol: T) -> bool {
    let r = T::from(1.0).unwrap().max(self.abs().max(y.abs()));
    self == y || ((self-y).abs() <= abs_tol * r)
  }

  fn equal(self, y: T) -> bool {
    self.almost_equal(y, T::from(EPSILON).unwrap())
  }
}
<commit_msg>add a clamp method to the Float trait<commit_after>extern crate num;

/// The default epsilon value used for floating point comparisons.
pub static EPSILON:f64 = 1.0E-8;

pub trait Float: num::Float{
  /// Tells if the two floating-point values `self` and `y` are considered equal
  /// within the specified `absolute == relative` tolerence value.
  ///
  /// The method of comparison used is described at:
  ///
  /// http://realtimecollisiondetection.net/blog/?p=89
  ///
  /// Also consider using the `equal` method.
  ///
  /// # Examples
  ///
  /// ```
  /// use fiz_math::Float;
  ///
  /// assert!(0.9.almost_equal(1.0, 0.1000001));
  /// assert!(0.9.almost_equal(1.0, 0.1));
  /// ```
  fn almost_equal(self, y: Self, abs_tol: Self) -> bool;

  /// equal is short-hand for `self.almost_equal(y, fiz_math::EPSILON)`.
  ///
  /// # Examples
  ///
  /// ```
  /// use fiz_math::Float;
  ///
  /// assert!(1.00000001.equal(1.0));
  /// assert!(1.0.equal(1.0));
  /// assert!(!0.9.equal(1.0));
  /// ```
  fn equal(self, y: Self) -> bool;

  /// clamp returns the value v clamped to the range of [min, max].
  ///
  /// # Examples
  ///
  /// ```
  /// use fiz_math::Float;
  ///
  /// assert_eq!(1.1.clamp(0.0, 1.0), 1.0);
  /// assert_eq!(2.0.clamp(0.0, 1.5), 1.5);
  /// ```
  ///
  /// ```
  /// use fiz_math::Float;
  ///
  /// assert_eq!((-1.0).clamp(0.0, 1.0), 0.0);
  /// assert_eq!(0.0.clamp(0.1, 1.0), 0.1);
  /// ```
  fn clamp(self, min: Self, max: Self) -> Self;
}

impl<T: num::Float> Float for T {
  fn almost_equal(self, y: T, abs_tol: T) -> bool {
    let r = T::from(1.0).unwrap().max(self.abs().max(y.abs()));
    self == y || ((self-y).abs() <= abs_tol * r)
  }

  fn equal(self, y: T) -> bool {
    self.almost_equal(y, T::from(EPSILON).unwrap())
  }

  fn clamp(self, min: Self, max: Self) -> Self {
    self.min(max).max(min)
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Result as IOResult;
use std::io::{Read, Write, ErrorKind, Cursor};
use std::error::Error;
use std::u16;

use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};

const FRAME_LEN_U16: u8 = 126;
const FRAME_LEN_U64: u8 = 127;

#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(dead_code)]
pub enum OpCode {
    TextFrame = 1,
    BinaryFrame = 2,
    ConnectionClose = 8,
    Ping = 9,
    Pong = 0xA
}

impl OpCode {
    fn from(op: u8) -> Option<OpCode> {
        match op {
            1 => Some(OpCode::TextFrame),
            2 => Some(OpCode::BinaryFrame),
            8 => Some(OpCode::ConnectionClose),
            9 => Some(OpCode::Ping),
            0xA => Some(OpCode::Pong),
            _ => None
        }
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct WebSocketFrameHeader {
    fin: bool,
    rsv1: bool,
    rsv2: bool,
    rsv3: bool,
    masked: bool,
    opcode: OpCode,
    payload_length: u8
}

impl WebSocketFrameHeader {
    fn new_header(len: usize, opcode: OpCode) -> WebSocketFrameHeader {
        WebSocketFrameHeader {
            fin: true,
            rsv1: false, rsv2: false, rsv3: false,
            masked: false,
            payload_length: Self::determine_len(len),
            opcode: opcode
        }
    }

    fn determine_len(len: usize) -> u8 {
        if len < (FRAME_LEN_U16 as usize) {
            len as u8
        } else if len < (u16::MAX as usize) {
            FRAME_LEN_U16
        } else {
            FRAME_LEN_U64
        }
    }
}

#[derive(Debug, Clone)]
pub struct WebSocketFrame {
    header: WebSocketFrameHeader,
    mask: Option<[u8; 4]>,
    pub payload: Vec<u8>
}

impl From<Vec<u8>> for WebSocketFrame {
    fn from(payload: Vec<u8>) -> WebSocketFrame {
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(payload.len(), OpCode::BinaryFrame),
            payload: payload,
            mask: None
        }
    }
}

impl<'a> From<&'a str> for WebSocketFrame {
    fn from(payload: &str) -> WebSocketFrame {
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(payload.len(), OpCode::TextFrame),
            payload: Vec::from(payload),
            mask: None
        }
    }
}

impl WebSocketFrame {
    pub fn close(status_code: u16, reason: &[u8]) -> Result<WebSocketFrame, String> {
        let body = Vec::with_capacity(2 + reason.len());

        let mut body_cursor = Cursor::new(body);

        try!(body_cursor.write_u16::<BigEndian>(status_code)
             .map_err(|e| e.description().to_string()));

        try!(body_cursor.write(reason)
             .map_err(|e| e.description().to_string()));

        Ok(WebSocketFrame {
            header: WebSocketFrameHeader::new_header(body_cursor.get_ref().len(), OpCode::ConnectionClose),
            payload: body_cursor.into_inner(),
            mask: None
        })
    }

    pub fn close_from(recv_frame: &WebSocketFrame) -> WebSocketFrame {
        let body = if recv_frame.payload.len() > 0 {
            let status_code = &recv_frame.payload[0..2];
            let mut body = Vec::with_capacity(2);
            body.write(status_code).unwrap();
            body
        } else {
            Vec::new()
        };
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(body.len(), OpCode::ConnectionClose),
            payload: body,
            mask: None
        }
    }

    pub fn pong(ping_frame: &WebSocketFrame) -> WebSocketFrame {
        let payload = ping_frame.payload.clone();
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(payload.len(), OpCode::Pong),
            payload: payload,
            mask: None
        }
    }

    pub fn ping(payload: Vec<u8>) -> WebSocketFrame {
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(4, OpCode::Ping),
            payload: payload,
            mask: None
        }
    }

    pub fn write<W: Write>(&self, output: &mut W) -> IOResult<()> {
        let hdr = Self::serialize_header(&self.header);
        try!(output.write_u16::<BigEndian>(hdr));

        match self.header.payload_length {
            FRAME_LEN_U16 => try!(output.write_u16::<BigEndian>(self.payload.len() as u16)),
            FRAME_LEN_U64 => try!(output.write_u64::<BigEndian>(self.payload.len() as u64)),
            _ => {}
        }

        try!(output.write(&self.payload));
        Ok(())
    }

    pub fn read<R: Read>(input: &mut R) -> IOResult<WebSocketFrame> {
        let buf = try!(input.read_u16::<BigEndian>());
        let header = try!(Self::parse_header(buf).map_err(|s| io::Error::new(ErrorKind::Other, s)));

        let len = try!(Self::read_length(header.payload_length, input));
        let mask_key = if header.masked {
            let mask = try!(Self::read_mask(input));
            Some(mask)
        } else {
            None
        };
        let mut payload = try!(Self::read_payload(len, input));

        if let Some(mask) = mask_key {
            Self::apply_mask(mask, &mut payload);
        }

        Ok(WebSocketFrame {
            header: header,
            payload: payload,
            mask: mask_key
        })
    }

    pub fn get_opcode(&self) -> OpCode {
        self.header.opcode.clone()
    }

    pub fn is_close(&self) -> bool {
        self.header.opcode == OpCode::ConnectionClose
    }

    fn serialize_header(hdr: &WebSocketFrameHeader) -> u16 {
        let b1 = ((hdr.fin as u8) << 7)
                  | ((hdr.rsv1 as u8) << 6)
                  | ((hdr.rsv2 as u8) << 5)
                  | ((hdr.rsv3 as u8) << 4)
                  | ((hdr.opcode as u8) & 0x0F);

        let b2 = ((hdr.masked as u8) << 7)
            | ((hdr.payload_length as u8) & 0x7F);

        ((b1 as u16) << 8) | (b2 as u16)
    }

    fn parse_header(buf: u16) -> Result<WebSocketFrameHeader, String> {
        let opcode_num = ((buf >> 8) as u8) & 0x0F;
        let opcode = OpCode::from(opcode_num);

        if let Some(opcode) = opcode {
            Ok(WebSocketFrameHeader {
                fin: (buf >> 8) & 0x80 == 0x80,
                rsv1: (buf >> 8) & 0x40 == 0x40,
                rsv2: (buf >> 8) & 0x20 == 0x20,
                rsv3: (buf >> 8) & 0x10 == 0x10,
                opcode: opcode,

                masked: buf & 0x80 == 0x80,
                payload_length: (buf as u8) & 0x7F,
            })
        } else {
            Err(format!("Invalid opcode: {}", opcode_num))
        }
    }

    fn apply_mask(mask: [u8; 4], bytes: &mut Vec<u8>) {
        for (idx, c) in bytes.iter_mut().enumerate() {
            *c = *c ^ mask[idx % 4];
        }
    }

    fn read_mask<R: Read>(input: &mut R) -> IOResult<[u8; 4]> {
        let mut buf = [0; 4];
        try!(input.read(&mut buf));
        Ok(buf)
    }

    fn read_payload<R: Read>(payload_len: usize, input: &mut R) -> IOResult<Vec<u8>> {
        let mut payload: Vec<u8> = Vec::with_capacity(payload_len);
        unsafe { payload.set_len(payload_len) };
        try!(input.read(&mut payload));
        Ok(payload)
    }

    fn read_length<R: Read>(payload_len: u8, input: &mut R) -> IOResult<usize> {
        return match payload_len {
            FRAME_LEN_U64 => input.read_u64::<BigEndian>().map(|v| v as usize).map_err(From::from),
            FRAME_LEN_U16 => input.read_u16::<BigEndian>().map(|v| v as usize).map_err(From::from),
            _ => Ok(payload_len as usize) // payload_len < 127
        }
    }
}
<commit_msg>Make code more clear by using a specific type<commit_after>use std::io;
use std::io::{Read, Write, ErrorKind, Cursor};
use std::error::Error;
use std::u16;

use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};

const FRAME_LEN_U16: u8 = 126;
const FRAME_LEN_U64: u8 = 127;

#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(dead_code)]
pub enum OpCode {
    TextFrame = 1,
    BinaryFrame = 2,
    ConnectionClose = 8,
    Ping = 9,
    Pong = 0xA
}

impl OpCode {
    fn from(op: u8) -> Option<OpCode> {
        match op {
            1 => Some(OpCode::TextFrame),
            2 => Some(OpCode::BinaryFrame),
            8 => Some(OpCode::ConnectionClose),
            9 => Some(OpCode::Ping),
            0xA => Some(OpCode::Pong),
            _ => None
        }
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct WebSocketFrameHeader {
    fin: bool,
    rsv1: bool,
    rsv2: bool,
    rsv3: bool,
    masked: bool,
    opcode: OpCode,
    payload_length: u8
}

impl WebSocketFrameHeader {
    fn new_header(len: usize, opcode: OpCode) -> WebSocketFrameHeader {
        WebSocketFrameHeader {
            fin: true,
            rsv1: false, rsv2: false, rsv3: false,
            masked: false,
            payload_length: Self::determine_len(len),
            opcode: opcode
        }
    }

    fn determine_len(len: usize) -> u8 {
        if len < (FRAME_LEN_U16 as usize) {
            len as u8
        } else if len < (u16::MAX as usize) {
            FRAME_LEN_U16
        } else {
            FRAME_LEN_U64
        }
    }
}

#[derive(Debug, Clone)]
pub struct WebSocketFrame {
    header: WebSocketFrameHeader,
    mask: Option<[u8; 4]>,
    pub payload: Vec<u8>
}

impl From<Vec<u8>> for WebSocketFrame {
    fn from(payload: Vec<u8>) -> WebSocketFrame {
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(payload.len(), OpCode::BinaryFrame),
            payload: payload,
            mask: None
        }
    }
}

impl<'a> From<&'a str> for WebSocketFrame {
    fn from(payload: &str) -> WebSocketFrame {
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(payload.len(), OpCode::TextFrame),
            payload: Vec::from(payload),
            mask: None
        }
    }
}

impl WebSocketFrame {
    pub fn close(status_code: u16, reason: &[u8]) -> Result<WebSocketFrame, String> {
        let body = Vec::with_capacity(2 + reason.len());

        let mut body_cursor = Cursor::new(body);

        try!(body_cursor.write_u16::<BigEndian>(status_code)
             .map_err(|e| e.description().to_string()));

        try!(body_cursor.write(reason)
             .map_err(|e| e.description().to_string()));

        Ok(WebSocketFrame {
            header: WebSocketFrameHeader::new_header(body_cursor.get_ref().len(), OpCode::ConnectionClose),
            payload: body_cursor.into_inner(),
            mask: None
        })
    }

    pub fn close_from(recv_frame: &WebSocketFrame) -> WebSocketFrame {
        let body = if recv_frame.payload.len() > 0 {
            let status_code = &recv_frame.payload[0..2];
            let mut body = Vec::with_capacity(2);
            body.write(status_code).unwrap();
            body
        } else {
            Vec::new()
        };
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(body.len(), OpCode::ConnectionClose),
            payload: body,
            mask: None
        }
    }

    pub fn pong(ping_frame: &WebSocketFrame) -> WebSocketFrame {
        let payload = ping_frame.payload.clone();
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(payload.len(), OpCode::Pong),
            payload: payload,
            mask: None
        }
    }

    pub fn ping(payload: Vec<u8>) -> WebSocketFrame {
        WebSocketFrame {
            header: WebSocketFrameHeader::new_header(4, OpCode::Ping),
            payload: payload,
            mask: None
        }
    }

    pub fn write<W: Write>(&self, output: &mut W) -> io::Result<()> {
        let hdr = Self::serialize_header(&self.header);
        try!(output.write_u16::<BigEndian>(hdr));

        match self.header.payload_length {
            FRAME_LEN_U16 => try!(output.write_u16::<BigEndian>(self.payload.len() as u16)),
            FRAME_LEN_U64 => try!(output.write_u64::<BigEndian>(self.payload.len() as u64)),
            _ => {}
        }

        try!(output.write(&self.payload));
        Ok(())
    }

    pub fn read<R: Read>(input: &mut R) -> io::Result<WebSocketFrame> {
        let buf = try!(input.read_u16::<BigEndian>());
        let header = try!(Self::parse_header(buf).map_err(|s| io::Error::new(ErrorKind::Other, s)));

        let len = try!(Self::read_length(header.payload_length, input));
        let mask_key = if header.masked {
            let mask = try!(Self::read_mask(input));
            Some(mask)
        } else {
            None
        };
        let mut payload = try!(Self::read_payload(len, input));

        if let Some(mask) = mask_key {
            Self::apply_mask(mask, &mut payload);
        }

        Ok(WebSocketFrame {
            header: header,
            payload: payload,
            mask: mask_key
        })
    }

    pub fn get_opcode(&self) -> OpCode {
        self.header.opcode.clone()
    }

    pub fn is_close(&self) -> bool {
        self.header.opcode == OpCode::ConnectionClose
    }

    fn serialize_header(hdr: &WebSocketFrameHeader) -> u16 {
        let b1 = ((hdr.fin as u8) << 7)
                  | ((hdr.rsv1 as u8) << 6)
                  | ((hdr.rsv2 as u8) << 5)
                  | ((hdr.rsv3 as u8) << 4)
                  | ((hdr.opcode as u8) & 0x0F);

        let b2 = ((hdr.masked as u8) << 7)
            | ((hdr.payload_length as u8) & 0x7F);

        ((b1 as u16) << 8) | (b2 as u16)
    }

    fn parse_header(buf: u16) -> Result<WebSocketFrameHeader, String> {
        let opcode_num = ((buf >> 8) as u8) & 0x0F;
        let opcode = OpCode::from(opcode_num);

        if let Some(opcode) = opcode {
            Ok(WebSocketFrameHeader {
                fin: (buf >> 8) & 0x80 == 0x80,
                rsv1: (buf >> 8) & 0x40 == 0x40,
                rsv2: (buf >> 8) & 0x20 == 0x20,
                rsv3: (buf >> 8) & 0x10 == 0x10,
                opcode: opcode,

                masked: buf & 0x80 == 0x80,
                payload_length: (buf as u8) & 0x7F,
            })
        } else {
            Err(format!("Invalid opcode: {}", opcode_num))
        }
    }

    fn apply_mask(mask: [u8; 4], bytes: &mut Vec<u8>) {
        for (idx, c) in bytes.iter_mut().enumerate() {
            *c = *c ^ mask[idx % 4];
        }
    }

    fn read_mask<R: Read>(input: &mut R) -> io::Result<[u8; 4]> {
        let mut buf = [0; 4];
        try!(input.read(&mut buf));
        Ok(buf)
    }

    fn read_payload<R: Read>(payload_len: usize, input: &mut R) -> io::Result<Vec<u8>> {
        let mut payload: Vec<u8> = Vec::with_capacity(payload_len);
        unsafe { payload.set_len(payload_len) };
        try!(input.read(&mut payload));
        Ok(payload)
    }

    fn read_length<R: Read>(payload_len: u8, input: &mut R) -> io::Result<usize> {
        return match payload_len {
            FRAME_LEN_U64 => input.read_u64::<BigEndian>().map(|v| v as usize).map_err(From::from),
            FRAME_LEN_U16 => input.read_u16::<BigEndian>().map(|v| v as usize).map_err(From::from),
            _ => Ok(payload_len as usize) // payload_len < 127
        }
    }
}
<|endoftext|>