<commit_before>//! Errors for `irc` crate using `failure`.

use std::io::Error as IoError;
use std::sync::mpsc::RecvError;

use futures::sync::mpsc::SendError;
use futures::sync::oneshot::Canceled;
use native_tls::Error as TlsError;
#[cfg(feature = "json")]
use serde_json::Error as JsonError;
#[cfg(feature = "yaml")]
use serde_yaml::Error as YamlError;
use tokio_timer::TimerError;
#[cfg(feature = "toml")]
use toml::de::Error as TomlReadError;
#[cfg(feature = "toml")]
use toml::ser::Error as TomlWriteError;

use proto::Message;

/// A specialized `Result` type for the `irc` crate.
pub type Result<T> = ::std::result::Result<T, IrcError>;

/// The main crate-wide error type.
#[derive(Debug, Fail)]
pub enum IrcError {
    /// An internal I/O error.
    #[fail(display = "an io error occurred")]
    Io(#[cause] IoError),

    /// An internal TLS error.
    #[fail(display = "a TLS error occurred")]
    Tls(#[cause] TlsError),

    /// An internal synchronous channel closed.
    #[fail(display = "a sync channel closed")]
    SyncChannelClosed(#[cause] RecvError),

    /// An internal asynchronous channel closed.
    #[fail(display = "an async channel closed")]
    AsyncChannelClosed(#[cause] SendError<Message>),

    /// An internal oneshot channel closed.
    #[fail(display = "a oneshot channel closed")]
    OneShotCanceled(#[cause] Canceled),

    /// An internal timer error.
    #[fail(display = "timer failed")]
    Timer(#[cause] TimerError),

    /// Error for invalid configurations.
    #[fail(display = "invalid config: {}", path)]
    InvalidConfig {
        /// The path to the configuration, or "<none>" if none specified.
        path: String,
        /// The detailed configuration error.
        #[cause]
        cause: ConfigError,
    },

    /// Error for invalid messages.
    #[fail(display = "invalid message: {}", string)]
    InvalidMessage {
        /// The string that failed to parse.
        string: String,
        /// The detailed message parsing error.
        #[cause]
        cause: MessageParseError,
    },

    /// Mutex for a logged transport was poisoned making the log inaccessible.
    #[fail(display = "mutex for a logged transport was poisoned")]
    PoisonedLog,

    /// Ping timed out due to no response.
    #[fail(display = "connection reset: no ping response")]
    PingTimeout,

    /// Failed to lookup an unknown codec.
    #[fail(display = "unknown codec: {}", codec)]
    UnknownCodec {
        /// The attempted codec.
        codec: String,
    },

    /// Failed to encode or decode something with the given codec.
    #[fail(display = "codec {} failed: {}", codec, data)]
    CodecFailed {
        /// The canonical codec name.
        codec: &'static str,
        /// The data that failed to encode or decode.
        data: String,
    },

    /// All specified nicks were in use or unusable.
    #[fail(display = "no usable nicks")]
    NoUsableNick
}

/// Errors that occur when parsing messages.
#[derive(Debug, Fail)]
pub enum MessageParseError {
    /// The message was empty.
    #[fail(display = "empty message")]
    EmptyMessage,

    /// The command was invalid (i.e. missing).
    #[fail(display = "invalid command")]
    InvalidCommand,

    /// The mode string was malformed.
    #[fail(display = "invalid mode string: {}", string)]
    InvalidModeString {
        /// The invalid mode string.
        string: String,
        /// The detailed mode parsing error.
        #[cause]
        cause: ModeParseError,
    },

    /// The subcommand used was invalid.
    #[fail(display = "invalid {} subcommand: {}", cmd, sub)]
    InvalidSubcommand {
        /// The command whose invalid subcommand was referenced.
        cmd: &'static str,
        /// The invalid subcommand.
        sub: String,
    }
}

/// Errors that occur while parsing mode strings.
#[derive(Debug, Fail)]
pub enum ModeParseError {
    /// Invalid modifier used in a mode string (only + and - are valid).
    #[fail(display = "invalid mode modifier: {}", modifier)]
    InvalidModeModifier {
        /// The invalid mode modifier.
        modifier: char,
    },

    /// Missing modifier used in a mode string.
    #[fail(display = "missing mode modifier")]
    MissingModeModifier,
}

/// Errors that occur with configurations.
#[derive(Debug, Fail)]
pub enum ConfigError {
    /// Failed to parse as TOML.
    #[cfg(feature = "toml")]
    #[fail(display = "invalid toml")]
    InvalidToml(#[cause] TomlError),

    /// Failed to parse as JSON.
    #[cfg(feature = "json")]
    #[fail(display = "invalid json")]
    InvalidJson(#[cause] JsonError),

    /// Failed to parse as YAML.
    #[cfg(feature = "yaml")]
    #[fail(display = "invalid yaml")]
    InvalidYaml(#[cause] YamlError),

    /// Failed to parse the given format because it was disabled at compile-time.
    #[fail(display = "config format disabled: {}", format)]
    ConfigFormatDisabled {
        /// The disabled file format.
        format: &'static str,
    },

    /// Could not identify the given file format.
    #[fail(display = "config format unknown: {}", format)]
    UnknownConfigFormat {
        /// The unknown file extension.
        format: String,
    },

    /// File was missing an extension to identify file format.
    #[fail(display = "missing format extension")]
    MissingExtension,

    /// Configuration does not specify a nickname.
    #[fail(display = "nickname not specified")]
    NicknameNotSpecified,

    /// Configuration does not specify a server.
    #[fail(display = "server not specified")]
    ServerNotSpecified,
}

/// A wrapper that combines toml's serialization and deserialization errors.
#[cfg(feature = "toml")]
#[derive(Debug, Fail)]
pub enum TomlError {
    /// A TOML deserialization error.
    #[fail(display = "deserialization failed")]
    Read(#[cause] TomlReadError),
    /// A TOML serialization error.
    #[fail(display = "serialization failed")]
    Write(#[cause] TomlWriteError),
}

impl From<IoError> for IrcError {
    fn from(e: IoError) -> IrcError {
        IrcError::Io(e)
    }
}

impl From<TlsError> for IrcError {
    fn from(e: TlsError) -> IrcError {
        IrcError::Tls(e)
    }
}

impl From<RecvError> for IrcError {
    fn from(e: RecvError) -> IrcError {
        IrcError::SyncChannelClosed(e)
    }
}

impl From<SendError<Message>> for IrcError {
    fn from(e: SendError<Message>) -> IrcError {
        IrcError::AsyncChannelClosed(e)
    }
}

impl From<Canceled> for IrcError {
    fn from(e: Canceled) -> IrcError {
        IrcError::OneShotCanceled(e)
    }
}

impl From<TimerError> for IrcError {
    fn from(e: TimerError) -> IrcError {
        IrcError::Timer(e)
    }
}
<commit_msg>Changed error message for NoUsableNick.<commit_after>//! Errors for `irc` crate using `failure`.

use std::io::Error as IoError;
use std::sync::mpsc::RecvError;

use futures::sync::mpsc::SendError;
use futures::sync::oneshot::Canceled;
use native_tls::Error as TlsError;
#[cfg(feature = "json")]
use serde_json::Error as JsonError;
#[cfg(feature = "yaml")]
use serde_yaml::Error as YamlError;
use tokio_timer::TimerError;
#[cfg(feature = "toml")]
use toml::de::Error as TomlReadError;
#[cfg(feature = "toml")]
use toml::ser::Error as TomlWriteError;

use proto::Message;

/// A specialized `Result` type for the `irc` crate.
pub type Result<T> = ::std::result::Result<T, IrcError>;

/// The main crate-wide error type.
#[derive(Debug, Fail)]
pub enum IrcError {
    /// An internal I/O error.
    #[fail(display = "an io error occurred")]
    Io(#[cause] IoError),

    /// An internal TLS error.
    #[fail(display = "a TLS error occurred")]
    Tls(#[cause] TlsError),

    /// An internal synchronous channel closed.
    #[fail(display = "a sync channel closed")]
    SyncChannelClosed(#[cause] RecvError),

    /// An internal asynchronous channel closed.
    #[fail(display = "an async channel closed")]
    AsyncChannelClosed(#[cause] SendError<Message>),

    /// An internal oneshot channel closed.
    #[fail(display = "a oneshot channel closed")]
    OneShotCanceled(#[cause] Canceled),

    /// An internal timer error.
    #[fail(display = "timer failed")]
    Timer(#[cause] TimerError),

    /// Error for invalid configurations.
    #[fail(display = "invalid config: {}", path)]
    InvalidConfig {
        /// The path to the configuration, or "<none>" if none specified.
        path: String,
        /// The detailed configuration error.
        #[cause]
        cause: ConfigError,
    },

    /// Error for invalid messages.
    #[fail(display = "invalid message: {}", string)]
    InvalidMessage {
        /// The string that failed to parse.
        string: String,
        /// The detailed message parsing error.
        #[cause]
        cause: MessageParseError,
    },

    /// Mutex for a logged transport was poisoned making the log inaccessible.
    #[fail(display = "mutex for a logged transport was poisoned")]
    PoisonedLog,

    /// Ping timed out due to no response.
    #[fail(display = "connection reset: no ping response")]
    PingTimeout,

    /// Failed to lookup an unknown codec.
    #[fail(display = "unknown codec: {}", codec)]
    UnknownCodec {
        /// The attempted codec.
        codec: String,
    },

    /// Failed to encode or decode something with the given codec.
    #[fail(display = "codec {} failed: {}", codec, data)]
    CodecFailed {
        /// The canonical codec name.
        codec: &'static str,
        /// The data that failed to encode or decode.
        data: String,
    },

    /// All specified nicknames were in use or unusable.
    #[fail(display = "none of the specified nicknames were usable")]
    NoUsableNick
}

/// Errors that occur when parsing messages.
#[derive(Debug, Fail)]
pub enum MessageParseError {
    /// The message was empty.
    #[fail(display = "empty message")]
    EmptyMessage,

    /// The command was invalid (i.e. missing).
    #[fail(display = "invalid command")]
    InvalidCommand,

    /// The mode string was malformed.
    #[fail(display = "invalid mode string: {}", string)]
    InvalidModeString {
        /// The invalid mode string.
        string: String,
        /// The detailed mode parsing error.
        #[cause]
        cause: ModeParseError,
    },

    /// The subcommand used was invalid.
    #[fail(display = "invalid {} subcommand: {}", cmd, sub)]
    InvalidSubcommand {
        /// The command whose invalid subcommand was referenced.
        cmd: &'static str,
        /// The invalid subcommand.
        sub: String,
    }
}

/// Errors that occur while parsing mode strings.
#[derive(Debug, Fail)]
pub enum ModeParseError {
    /// Invalid modifier used in a mode string (only + and - are valid).
    #[fail(display = "invalid mode modifier: {}", modifier)]
    InvalidModeModifier {
        /// The invalid mode modifier.
        modifier: char,
    },

    /// Missing modifier used in a mode string.
    #[fail(display = "missing mode modifier")]
    MissingModeModifier,
}

/// Errors that occur with configurations.
#[derive(Debug, Fail)]
pub enum ConfigError {
    /// Failed to parse as TOML.
    #[cfg(feature = "toml")]
    #[fail(display = "invalid toml")]
    InvalidToml(#[cause] TomlError),

    /// Failed to parse as JSON.
    #[cfg(feature = "json")]
    #[fail(display = "invalid json")]
    InvalidJson(#[cause] JsonError),

    /// Failed to parse as YAML.
    #[cfg(feature = "yaml")]
    #[fail(display = "invalid yaml")]
    InvalidYaml(#[cause] YamlError),

    /// Failed to parse the given format because it was disabled at compile-time.
    #[fail(display = "config format disabled: {}", format)]
    ConfigFormatDisabled {
        /// The disabled file format.
        format: &'static str,
    },

    /// Could not identify the given file format.
    #[fail(display = "config format unknown: {}", format)]
    UnknownConfigFormat {
        /// The unknown file extension.
        format: String,
    },

    /// File was missing an extension to identify file format.
    #[fail(display = "missing format extension")]
    MissingExtension,

    /// Configuration does not specify a nickname.
    #[fail(display = "nickname not specified")]
    NicknameNotSpecified,

    /// Configuration does not specify a server.
    #[fail(display = "server not specified")]
    ServerNotSpecified,
}

/// A wrapper that combines toml's serialization and deserialization errors.
#[cfg(feature = "toml")]
#[derive(Debug, Fail)]
pub enum TomlError {
    /// A TOML deserialization error.
    #[fail(display = "deserialization failed")]
    Read(#[cause] TomlReadError),
    /// A TOML serialization error.
    #[fail(display = "serialization failed")]
    Write(#[cause] TomlWriteError),
}

impl From<IoError> for IrcError {
    fn from(e: IoError) -> IrcError {
        IrcError::Io(e)
    }
}

impl From<TlsError> for IrcError {
    fn from(e: TlsError) -> IrcError {
        IrcError::Tls(e)
    }
}

impl From<RecvError> for IrcError {
    fn from(e: RecvError) -> IrcError {
        IrcError::SyncChannelClosed(e)
    }
}

impl From<SendError<Message>> for IrcError {
    fn from(e: SendError<Message>) -> IrcError {
        IrcError::AsyncChannelClosed(e)
    }
}

impl From<Canceled> for IrcError {
    fn from(e: Canceled) -> IrcError {
        IrcError::OneShotCanceled(e)
    }
}

impl From<TimerError> for IrcError {
    fn from(e: TimerError) -> IrcError {
        IrcError::Timer(e)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! `Error` binding and helper trait.

use std::ffi::CStr;
use Quark;
use std::error;
use std::fmt;
use std::str;
use std::ptr;
use std::mem;
use translate::*;
use ffi as glib_ffi;
use gobject_ffi;

glib_wrapper! {
    /// A generic error capable of representing various error domains (types).
    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct Error(Boxed<glib_ffi::GError>);

    match fn {
        copy => |ptr| glib_ffi::g_error_copy(ptr),
        free => |ptr| glib_ffi::g_error_free(ptr),
        get_type => || glib_ffi::g_error_get_type(),
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Error {
    /// Creates an error with supplied error enum variant and message.
    pub fn new<T: ErrorDomain>(error: T, message: &str) -> Error {
        unsafe {
            from_glib_full(
                glib_ffi::g_error_new_literal(T::domain().to_glib(), error.code(), message.to_glib_none().0))
        }
    }

    /// Checks if the error domain matches `T`.
    pub fn is<T: ErrorDomain>(&self) -> bool {
        self.0.domain == T::domain().to_glib()
    }

    /// Tries to convert to a specific error enum.
    ///
    /// Returns `Some` if the error belongs to the enum's error domain and
    /// `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// if let Some(file_error) = error.kind::<FileError>() {
    ///     match file_error {
    ///         FileError::Exist => ...
    ///         FileError::Isdir => ...
    ///         ...
    ///     }
    /// }
    /// ```
    ///
    /// ```ignore
    /// match error {
    ///     Some(FileError::Exist) => ...
    ///     Some(FileError::Isdir) => ...
    ///     ...
    /// }
    /// ```
    pub fn kind<T: ErrorDomain>(&self) -> Option<T> {
        if self.0.domain == T::domain().to_glib() {
            T::from(self.0.code)
        }
        else {
            None
        }
    }

    fn message(&self) -> &str {
        unsafe {
            let bytes = CStr::from_ptr(self.0.message).to_bytes();
            str::from_utf8(bytes).unwrap_or_else(|err| {
                str::from_utf8(&bytes[..err.valid_up_to()]).unwrap()
            })
        }
    }

    // backcompat shim
    #[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
    pub fn wrap(ptr: *mut glib_ffi::GError) -> Error {
        unsafe { from_glib_full(ptr) }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.message())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        self.message()
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("domain", &self.0.domain)
            .field("code", &self.0.code)
            .field("message", &self.message())
            .finish()
    }
}

/// `GLib` error domain.
///
/// This trait is implemented by error enums that represent error domains (types).
pub trait ErrorDomain: Copy {
    /// Returns the quark identifying the error domain.
    ///
    /// As returned from `g_some_error_quark`.
    fn domain() -> Quark;

    /// Gets the integer representation of the variant.
    fn code(self) -> i32;

    /// Tries to convert an integer code to an enum variant.
    ///
    /// By convention, the `Failed` variant, if present, is a catch-all,
    /// i.e. any unrecognized codes map to it.
    fn from(code: i32) -> Option<Self> where Self: Sized;
}

/// Generic error used for functions that fail without any further information
#[derive(Debug)]
pub struct BoolError(pub &'static str);

impl BoolError {
    pub fn from_glib(b: glib_ffi::gboolean, s: &'static str) -> Result<(), Self> {
        match b {
            glib_ffi::GFALSE => Err(BoolError(s)),
            _ => Ok(()),
        }
    }
}

impl fmt::Display for BoolError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl error::Error for BoolError {
    fn description(&self) -> &str {
        self.0
    }
}
<commit_msg>Print error quark as string in the Debug impl<commit_after>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! `Error` binding and helper trait.

use std::ffi::CStr;
use Quark;
use std::error;
use std::fmt;
use std::str;
use std::ptr;
use std::mem;
use translate::*;
use ffi as glib_ffi;
use gobject_ffi;

glib_wrapper! {
    /// A generic error capable of representing various error domains (types).
    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct Error(Boxed<glib_ffi::GError>);

    match fn {
        copy => |ptr| glib_ffi::g_error_copy(ptr),
        free => |ptr| glib_ffi::g_error_free(ptr),
        get_type => || glib_ffi::g_error_get_type(),
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Error {
    /// Creates an error with supplied error enum variant and message.
    pub fn new<T: ErrorDomain>(error: T, message: &str) -> Error {
        unsafe {
            from_glib_full(
                glib_ffi::g_error_new_literal(T::domain().to_glib(), error.code(), message.to_glib_none().0))
        }
    }

    /// Checks if the error domain matches `T`.
    pub fn is<T: ErrorDomain>(&self) -> bool {
        self.0.domain == T::domain().to_glib()
    }

    /// Tries to convert to a specific error enum.
    ///
    /// Returns `Some` if the error belongs to the enum's error domain and
    /// `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// if let Some(file_error) = error.kind::<FileError>() {
    ///     match file_error {
    ///         FileError::Exist => ...
    ///         FileError::Isdir => ...
    ///         ...
    ///     }
    /// }
    /// ```
    ///
    /// ```ignore
    /// match error {
    ///     Some(FileError::Exist) => ...
    ///     Some(FileError::Isdir) => ...
    ///     ...
    /// }
    /// ```
    pub fn kind<T: ErrorDomain>(&self) -> Option<T> {
        if self.0.domain == T::domain().to_glib() {
            T::from(self.0.code)
        }
        else {
            None
        }
    }

    fn message(&self) -> &str {
        unsafe {
            let bytes = CStr::from_ptr(self.0.message).to_bytes();
            str::from_utf8(bytes).unwrap_or_else(|err| {
                str::from_utf8(&bytes[..err.valid_up_to()]).unwrap()
            })
        }
    }

    // backcompat shim
    #[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
    pub fn wrap(ptr: *mut glib_ffi::GError) -> Error {
        unsafe { from_glib_full(ptr) }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.message())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        self.message()
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("domain", &::Quark::from_glib(self.0.domain))
            .field("code", &self.0.code)
            .field("message", &self.message())
            .finish()
    }
}

/// `GLib` error domain.
///
/// This trait is implemented by error enums that represent error domains (types).
pub trait ErrorDomain: Copy {
    /// Returns the quark identifying the error domain.
    ///
    /// As returned from `g_some_error_quark`.
    fn domain() -> Quark;

    /// Gets the integer representation of the variant.
    fn code(self) -> i32;

    /// Tries to convert an integer code to an enum variant.
    ///
    /// By convention, the `Failed` variant, if present, is a catch-all,
    /// i.e. any unrecognized codes map to it.
    fn from(code: i32) -> Option<Self> where Self: Sized;
}

/// Generic error used for functions that fail without any further information
#[derive(Debug)]
pub struct BoolError(pub &'static str);

impl BoolError {
    pub fn from_glib(b: glib_ffi::gboolean, s: &'static str) -> Result<(), Self> {
        match b {
            glib_ffi::GFALSE => Err(BoolError(s)),
            _ => Ok(()),
        }
    }
}

impl fmt::Display for BoolError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl error::Error for BoolError {
    fn description(&self) -> &str {
        self.0
    }
}
<|endoftext|>


<commit_before>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;
}
<commit_msg>Auto merge of #72 - msanders:ms/cgevent-type, r=jdm<commit_after>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }

    pub fn set_type(&self, event_type: CGEventType) {
        unsafe {
            CGEventSetType(self.as_concrete_TypeRef(), event_type);
        }
    }

    pub fn get_type(&self) -> CGEventType {
        unsafe {
            CGEventGetType(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;

    /// Set the event type of an event.
    fn CGEventSetType(event: CGEventRef, eventType: CGEventType);

    /// Return the event type of an event (left mouse down, for example).
    fn CGEventGetType(event: CGEventRef) -> CGEventType;
}
<|endoftext|>


<commit_before>fn main() {
    let s: i64 = 24;
    let half_s: i64 = s / 2;
    let m_limit: i64 = (s as f64).sqrt() as i64 + 1;
    // let a = (m^2 - n^2) ·d
    // let b = 2·m·n·d
    // let c = (m^2 + n^2) ·d
    // m > n && gcd(m, n) == 1

    /* (1)
     * 2 x d x m x (m + n) = s
     *     => m x (m + n) = s / (2 x d)
     *     => m^2 < s / (2 x d)
     *     => m^2 < s / 2
     *     => m <= round((s / 2)^0.5)
     * (2)
     * m > n > 0
     *     => m >= 2
     * (3)
     * s / 2 = m x d x (m + n)
     *     => (s / 2) % m == 0
     */
    for m in 2..m_limit {
        if half_s % m == 0 {
            /*
             * (1)
             * k = m + n
             *     => k % 2 == 1
             * (2)
             * m < k = m + n < 2m
             * (3)
             * s / 2 = m x d x (m + n)
             *     => k = (m + n) = (s / 2) / (m x d) < s / 2m
             *
             */
            let k_start = if m % 2 == 0 {
                m + 1
            } else {
                m + 2
            };

            let mut half_s_div_m: i64 = s / (2 * m);
            while half_s_div_m % 2 == 0 {
                half_s_div_m = half_s_div_m / 2;
            }

            let k_end = if 2 * m  < half_s_div_m  {
                2 * m
            } else {
                half_s_div_m + 1
            };

            for k in k_start..k_end {
                // gcd(m, n) == 1 => gcd(m, m + n) == 1 => gcd(m, k) == 1
                if (half_s/ m) % k == 0 && 1 == gcd(m, k) {
                    let d: i64 = half_s / (m * k);
                    let n: i64 = k - m;
                    let a: i64 = (m * m - n * n) * d;
                    let b: i64 = (2 * m * n) * d;
                    let c: i64 = (m * m + n * n) * d;
                    println!("a: {}, b: {}, c: {}", a, b ,c);
                    break;
                }
                // k += 2;
            }
        }
    }
}

fn gcd(x: i64, y: i64) -> i64 {
    let (mut a, mut b) = if x > y {
        (x, y)
    } else {
        (y, x)
    };

    while b != 0 {
        let r = a % b;
        a = b;
        b = r;
    }

    a
}
<commit_msg>add 2nd solution of SummationOfPrimes<commit_after>fn main() {
    // sieve[i] == 1 stands for 2 * i + 1 is not prime
    // sieve[i] == 0 stands for 2 * i + 1 is prime
    let mut sieve = vec![0; 999999];
    let i_limit: u32 = ((2000000 as f64).sqrt() as u32 - 1) / 2;

    for i in 1..i_limit {
        let index = i as usize;
        if sieve[index] == 0 {
            let mut j: usize = 2 * index * (index + 1);
            while j < 999999 {
                sieve[j] = 1;
                j = j + 2 * index + 1;
            }
        }
    }

    let mut result: i64 = 2;
    for k in 1..999999 {
        if sieve[k] == 0 {
            result = result + 2 * k as i64 + 1;
        }
    }

    println!("{}", result);
}
<|endoftext|>


<commit_before>use super::IntegPointData;
use crate::shapes::Scratchpad;
use crate::StrError;
use russell_lab::Vector;

/// Implements the the shape(N) times vector(V) integration case (boundary integral version)
///
/// Interpolation functions times vector field:
///
/// ```text
/// →    ⌠    → →   → →
/// bᵐ = │ Nᵐ(x(ξ)) t(x) tₕ dΓ
///      ⌡
///      Γₑ
/// ```
///
/// The numerical integration is:
///
/// ```text
/// →    nip-1     →   → →        →   →
/// bᵐ ≈   Σ    Nᵐ(ιᵖ) t(ιᵖ) tₕ ||n||(ιᵖ) wᵖ
///       p=0
/// ```
///
/// # Output
///
/// ```text
///     ┌     ┐
///     | b⁰₀ |
///     | b⁰₁ |
///     | b¹₀ |
/// b = | b¹₁ |
///     | b²₀ |
///     | b²₁ |
///     | ··· |
///     | bᵐᵢ |  ⟸  ii := i + m * space_ndim
///     └     ┘
///
/// m = ii / space_ndim
/// i = ii % space_ndim
/// ```
///
/// * `b` -- A vector containing all `bᵐᵢ` values, one after another, and sequentially placed
///          as shown above (in 2D). `m` is the index of the node and `i` corresponds to `space_ndim`.
///          The length of `b` must be equal to `nnode * space_ndim`.
///
/// # Input
///
/// * `pad` -- **modified** Scratchpad
/// * `ips` -- Integration points (n_integ_point)
/// * `th` -- tₕ the out-of-plane thickness in 2D or 1.0 otherwise (e.g., for plane-stress models)
/// * `clear_b` -- fills `b` vector with zeros, otherwise accumulate values into `b`
/// * `fn_t` -- Function `f(t,p,n)` that calculates `t(x(ιᵖ))` with `0 ≤ p ≤ n_integ_point`
///    and given the normal vector `n(x(ιᵖ))`. The dim of `v` and `n` is equal to `space_ndim`.
///
/// # Examples
///
pub fn vec_b_shape_times_vector_boundary<F>(
    b: &mut Vector,
    pad: &mut Scratchpad,
    ips: IntegPointData,
    th: f64,
    clear_b: bool,
    fn_t: F,
) -> Result<(), StrError>
where
    F: Fn(&mut Vector, usize, &Vector) -> Result<(), StrError>,
{
    // check
    let nnode = pad.interp.dim();
    let space_ndim = pad.xmax.len();
    if b.dim() != nnode * space_ndim {
        return Err("b.len() must be equal to nnode * space_ndim");
    }

    // allocate auxiliary vectors
    let mut t = Vector::new(space_ndim);
    let mut n = Vector::new(space_ndim); // normal vector

    // clear output vector
    if clear_b {
        b.fill(0.0);
    }

    // loop over integration points
    for p in 0..ips.len() {
        // ksi coordinates and weight
        let iota = &ips[p];
        let weight = ips[p][3];

        // calculate interpolation functions and normal vector
        (pad.fn_interp)(&mut pad.interp, iota);
        let mag_n = pad.calc_normal_vector(&mut n, iota)?;

        // calculate t
        fn_t(&mut t, p, &n)?;

        // add contribution to b vector
        let coef = th * mag_n * weight;
        let nn = &pad.interp;
        if space_ndim == 2 {
            for m in 0..nnode {
                b[0 + m * 2] += coef * nn[m] * t[0];
                b[1 + m * 2] += coef * nn[m] * t[1];
            }
        } else {
            for m in 0..nnode {
                b[0 + m * 3] += coef * nn[m] * t[0];
                b[1 + m * 3] += coef * nn[m] * t[1];
                b[2 + m * 3] += coef * nn[m] * t[2];
            }
        }
    }
    Ok(())
}

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

#[cfg(test)]
mod tests {
    use super::vec_b_shape_times_vector_boundary;
    use crate::integ::default_integ_points;
    use crate::shapes::{GeoKind, Scratchpad};
    use russell_chk::assert_vec_approx_eq;
    use russell_lab::Vector;

    // to test if variables are cleared before sum
    const NOISE: f64 = 1234.56;

    #[test]
    fn vec_b_shape_times_vector_boundary_works_2d() {
        let space_ndim = 2;
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Lin2).unwrap();
        let ll = 4.0;
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(1, 0, ll);
        pad.set_xx(1, 1, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(b.as_data(), &[0.0, -2.0, 0.0, -2.0], 1e-15);

        // example from [@sgm:14]\page{183}
        // * `sgm:14` -- Smith, Griffiths, Margetts (2014) Programming the Finite Element Method, 5th ed.
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Lin3).unwrap();
        let ll = 3.0;
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(1, 0, ll);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(2, 0, ll / 2.0);
        pad.set_xx(2, 1, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(b.as_data(), &[0.0, -0.5, 0.0, -0.5, 0.0, -2.0], 1e-15);
    }

    #[test]
    fn vec_b_shape_times_vector_boundary_works_3d() {
        let space_ndim = 3;
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Qua4).unwrap();
        let (dx, dy) = (0.5, 1.0);
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(0, 2, 0.0);
        pad.set_xx(1, 0, dx);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(1, 2, 0.0);
        pad.set_xx(2, 0, dx);
        pad.set_xx(2, 1, dy);
        pad.set_xx(2, 2, 0.0);
        pad.set_xx(3, 0, 0.0);
        pad.set_xx(3, 1, dy);
        pad.set_xx(3, 2, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = 0.0;
            t[2] = -1.0;
            Ok(())
        })
        .unwrap();
        let aa = dx * dy;
        assert_vec_approx_eq!(
            b.as_data(),
            &[
                0.0,
                0.0,
                -aa / 4.0, // 0
                0.0,
                0.0,
                -aa / 4.0, // 1
                0.0,
                0.0,
                -aa / 4.0, // 2
                0.0,
                0.0,
                -aa / 4.0, // 3
            ],
            1e-15
        );

        // example from [@sgm:14]\page{195}
        // * `sgm:14` -- Smith, Griffiths, Margetts (2014) Programming the Finite Element Method, 5th ed.
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Qua8).unwrap();
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(0, 2, 0.0);
        pad.set_xx(1, 0, dx);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(1, 2, 0.0);
        pad.set_xx(2, 0, dx);
        pad.set_xx(2, 1, dy);
        pad.set_xx(2, 2, 0.0);
        pad.set_xx(3, 0, 0.0);
        pad.set_xx(3, 1, dy);
        pad.set_xx(3, 2, 0.0);
        pad.set_xx(4, 0, dx / 2.0);
        pad.set_xx(4, 1, 0.0);
        pad.set_xx(4, 2, 0.0);
        pad.set_xx(5, 0, dx);
        pad.set_xx(5, 1, dy / 2.0);
        pad.set_xx(5, 2, 0.0);
        pad.set_xx(6, 0, dx / 2.0);
        pad.set_xx(6, 1, dy);
        pad.set_xx(6, 2, 0.0);
        pad.set_xx(7, 0, 0.0);
        pad.set_xx(7, 1, dy / 2.0);
        pad.set_xx(7, 2, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = 0.0;
            t[2] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(
            b.as_data(),
            &[
                0.0,
                0.0,
                aa / 12.0, // 0
                0.0,
                0.0,
                aa / 12.0, // 1
                0.0,
                0.0,
                aa / 12.0, // 2
                0.0,
                0.0,
                aa / 12.0, // 3
                0.0,
                0.0,
                -aa / 3.0, // 4
                0.0,
                0.0,
                -aa / 3.0, // 5
                0.0,
                0.0,
                -aa / 3.0, // 6
                0.0,
                0.0,
                -aa / 3.0, // 7
            ],
            1e-15
        );
    }
}
<commit_msg>Add tests for boundary integ<commit_after>use super::IntegPointData;
use crate::shapes::Scratchpad;
use crate::StrError;
use russell_lab::Vector;

/// Implements the the shape(N) times vector(V) integration case (boundary integral version)
///
/// Interpolation functions times vector field:
///
/// ```text
/// →    ⌠    → →   → →
/// bᵐ = │ Nᵐ(x(ξ)) t(x) tₕ dΓ
///      ⌡
///      Γₑ
/// ```
///
/// The numerical integration is:
///
/// ```text
/// →    nip-1     →   → →        →   →
/// bᵐ ≈   Σ    Nᵐ(ιᵖ) t(ιᵖ) tₕ ||n||(ιᵖ) wᵖ
///       p=0
/// ```
///
/// # Output
///
/// ```text
///     ┌     ┐
///     | b⁰₀ |
///     | b⁰₁ |
///     | b¹₀ |
/// b = | b¹₁ |
///     | b²₀ |
///     | b²₁ |
///     | ··· |
///     | bᵐᵢ |  ⟸  ii := i + m * space_ndim
///     └     ┘
///
/// m = ii / space_ndim
/// i = ii % space_ndim
/// ```
///
/// * `b` -- A vector containing all `bᵐᵢ` values, one after another, and sequentially placed
///          as shown above (in 2D). `m` is the index of the node and `i` corresponds to `space_ndim`.
///          The length of `b` must be equal to `nnode * space_ndim`.
///
/// # Input
///
/// * `pad` -- **modified** Scratchpad
/// * `ips` -- Integration points (n_integ_point)
/// * `th` -- tₕ the out-of-plane thickness in 2D or 1.0 otherwise (e.g., for plane-stress models)
/// * `clear_b` -- fills `b` vector with zeros, otherwise accumulate values into `b`
/// * `fn_t` -- Function `f(t,p,n)` that calculates `t(x(ιᵖ))` with `0 ≤ p ≤ n_integ_point`
///    and given the normal vector `n(x(ιᵖ))`. The dim of `v` and `n` is equal to `space_ndim`.
///
/// # Examples
///
pub fn vec_b_shape_times_vector_boundary<F>(
    b: &mut Vector,
    pad: &mut Scratchpad,
    ips: IntegPointData,
    th: f64,
    clear_b: bool,
    fn_t: F,
) -> Result<(), StrError>
where
    F: Fn(&mut Vector, usize, &Vector) -> Result<(), StrError>,
{
    // check
    let nnode = pad.interp.dim();
    let space_ndim = pad.xmax.len();
    if b.dim() != nnode * space_ndim {
        return Err("b.len() must be equal to nnode * space_ndim");
    }

    // allocate auxiliary vectors
    let mut t = Vector::new(space_ndim);
    let mut n = Vector::new(space_ndim); // normal vector

    // clear output vector
    if clear_b {
        b.fill(0.0);
    }

    // loop over integration points
    for p in 0..ips.len() {
        // ksi coordinates and weight
        let iota = &ips[p];
        let weight = ips[p][3];

        // calculate interpolation functions and normal vector
        (pad.fn_interp)(&mut pad.interp, iota);
        let mag_n = pad.calc_normal_vector(&mut n, iota)?;

        // calculate t
        fn_t(&mut t, p, &n)?;

        // add contribution to b vector
        let coef = th * mag_n * weight;
        let nn = &pad.interp;
        if space_ndim == 2 {
            for m in 0..nnode {
                b[0 + m * 2] += coef * nn[m] * t[0];
                b[1 + m * 2] += coef * nn[m] * t[1];
            }
        } else {
            for m in 0..nnode {
                b[0 + m * 3] += coef * nn[m] * t[0];
                b[1 + m * 3] += coef * nn[m] * t[1];
                b[2 + m * 3] += coef * nn[m] * t[2];
            }
        }
    }
    Ok(())
}

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

#[cfg(test)]
mod tests {
    use super::vec_b_shape_times_vector_boundary;
    use crate::integ::{calc_ips_coords, default_integ_points};
    use crate::shapes::{GeoKind, Scratchpad};
    use russell_chk::assert_vec_approx_eq;
    use russell_lab::Vector;

    // to test if variables are cleared before sum
    const NOISE: f64 = 1234.56;

    #[test]
    fn vec_b_shape_times_vector_boundary_works_2d() {
        // Reference:
        // * `sgm:14` -- Smith, Griffiths, Margetts (2014) Programming the Finite Element Method, 5th ed.

        let space_ndim = 2;
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Lin2).unwrap();
        let ll = 4.0;
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(1, 0, ll);
        pad.set_xx(1, 1, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        // uniform
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(b.as_data(), &[0.0, -2.0, 0.0, -2.0], 1e-15);
        // triangular (see [@sgm:14]\page{605})
        let x_ips = calc_ips_coords(&mut pad, ips).unwrap();
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, p, _| {
            let c = x_ips[p][0] / ll;
            t[0] = 0.0;
            t[1] = -c;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(b.as_data(), &[0.0, -ll / 6.0, 0.0, -ll / 3.0], 1e-15);

        // example from [@sgm:14]\page{183}
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Lin3).unwrap();
        let ll = 3.0;
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(1, 0, ll);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(2, 0, ll / 2.0);
        pad.set_xx(2, 1, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        // uniform
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(b.as_data(), &[0.0, -0.5, 0.0, -0.5, 0.0, -2.0], 1e-15);
        // triangular (see [@sgm:14]\page{605})
        let x_ips = calc_ips_coords(&mut pad, ips).unwrap();
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, p, _| {
            let c = x_ips[p][0] / ll;
            t[0] = 0.0;
            t[1] = -c;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(b.as_data(), &[0.0, 0.0, 0.0, -ll / 6.0, 0.0, -ll / 3.0], 1e-15);

        // example from [@sgm:14]\page{183}
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Lin5).unwrap();
        let ll = 4.0;
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(1, 0, ll);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(2, 0, ll / 2.0);
        pad.set_xx(2, 1, 0.0);
        pad.set_xx(3, 0, ll / 4.0);
        pad.set_xx(3, 1, 0.0);
        pad.set_xx(4, 0, 3.0 * ll / 4.0);
        pad.set_xx(4, 1, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        // uniform
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(
            b.as_data(),
            &[
                0.0,
                -ll * 7.0 / 90.0, // 0
                0.0,
                -ll * 7.0 / 90.0, // 1
                0.0,
                -ll * 2.0 / 15.0, // 2
                0.0,
                -ll * 16.0 / 45.0, // 3
                0.0,
                -ll * 16.0 / 45.0, // 4
            ],
            1e-15
        );
        // triangular (see [@sgm:14]\page{605})
        let x_ips = calc_ips_coords(&mut pad, ips).unwrap();
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, p, _| {
            let c = x_ips[p][0] / ll;
            t[0] = 0.0;
            t[1] = -c;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(
            b.as_data(),
            &[
                0.0,
                0.0, // 0
                0.0,
                -ll * 7.0 / 90.0, // 1
                0.0,
                -ll * 1.0 / 15.0, // 2
                0.0,
                -ll * 4.0 / 45.0, // 3
                0.0,
                -ll * 4.0 / 15.0, // 4
            ],
            1e-15
        );
    }

    #[test]
    fn vec_b_shape_times_vector_boundary_works_3d() {
        let space_ndim = 3;
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Qua4).unwrap();
        let (dx, dy) = (0.5, 1.0);
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(0, 2, 0.0);
        pad.set_xx(1, 0, dx);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(1, 2, 0.0);
        pad.set_xx(2, 0, dx);
        pad.set_xx(2, 1, dy);
        pad.set_xx(2, 2, 0.0);
        pad.set_xx(3, 0, 0.0);
        pad.set_xx(3, 1, dy);
        pad.set_xx(3, 2, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = 0.0;
            t[2] = -1.0;
            Ok(())
        })
        .unwrap();
        let aa = dx * dy;
        assert_vec_approx_eq!(
            b.as_data(),
            &[
                0.0,
                0.0,
                -aa / 4.0, // 0
                0.0,
                0.0,
                -aa / 4.0, // 1
                0.0,
                0.0,
                -aa / 4.0, // 2
                0.0,
                0.0,
                -aa / 4.0, // 3
            ],
            1e-15
        );

        // example from [@sgm:14]\page{195}
        // * `sgm:14` -- Smith, Griffiths, Margetts (2014) Programming the Finite Element Method, 5th ed.
        let mut pad = Scratchpad::new(space_ndim, GeoKind::Qua8).unwrap();
        pad.set_xx(0, 0, 0.0);
        pad.set_xx(0, 1, 0.0);
        pad.set_xx(0, 2, 0.0);
        pad.set_xx(1, 0, dx);
        pad.set_xx(1, 1, 0.0);
        pad.set_xx(1, 2, 0.0);
        pad.set_xx(2, 0, dx);
        pad.set_xx(2, 1, dy);
        pad.set_xx(2, 2, 0.0);
        pad.set_xx(3, 0, 0.0);
        pad.set_xx(3, 1, dy);
        pad.set_xx(3, 2, 0.0);
        pad.set_xx(4, 0, dx / 2.0);
        pad.set_xx(4, 1, 0.0);
        pad.set_xx(4, 2, 0.0);
        pad.set_xx(5, 0, dx);
        pad.set_xx(5, 1, dy / 2.0);
        pad.set_xx(5, 2, 0.0);
        pad.set_xx(6, 0, dx / 2.0);
        pad.set_xx(6, 1, dy);
        pad.set_xx(6, 2, 0.0);
        pad.set_xx(7, 0, 0.0);
        pad.set_xx(7, 1, dy / 2.0);
        pad.set_xx(7, 2, 0.0);
        let mut b = Vector::filled(pad.kind.nnode() * space_ndim, NOISE);
        let ips = default_integ_points(pad.kind);
        vec_b_shape_times_vector_boundary(&mut b, &mut pad, ips, 1.0, true, |t, _, _| {
            t[0] = 0.0;
            t[1] = 0.0;
            t[2] = -1.0;
            Ok(())
        })
        .unwrap();
        assert_vec_approx_eq!(
            b.as_data(),
            &[
                0.0,
                0.0,
                aa / 12.0, // 0
                0.0,
                0.0,
                aa / 12.0, // 1
                0.0,
                0.0,
                aa / 12.0, // 2
                0.0,
                0.0,
                aa / 12.0, // 3
                0.0,
                0.0,
                -aa / 3.0, // 4
                0.0,
                0.0,
                -aa / 3.0, // 5
                0.0,
                0.0,
                -aa / 3.0, // 6
                0.0,
                0.0,
                -aa / 3.0, // 7
            ],
            1e-15
        );
    }
}
<|endoftext|>


<commit_before>use gemlab::StrError;
use russell_lab::Vector;

struct Processor<'a> {
    callback: Option<Box<dyn FnMut(&mut Vector, &[f64]) -> Result<(), StrError> + 'a>>,
}

impl<'a> Processor<'a> {
    fn set_callback(&mut self, c: impl FnMut(&mut Vector, &[f64]) -> Result<(), StrError> + 'a) {
        self.callback = Some(Box::new(c));
    }

    fn process_events(&mut self) -> Result<(), StrError> {
        let ksi = vec![0.0; 2];
        let mut x = Vector::new(2);
        // (self.callback)(&mut x, &ksi);
        match &mut self.callback {
            Some(a) => a(&mut x, &ksi)?,
            None => (),
        }
        println!("got x =\n{}", x);
        Ok(())
    }
}

fn simple_callback(_: &mut Vector, _: &[f64]) -> Result<(), StrError> {
    Err("nothing to see here")
}

fn main() -> Result<(), StrError> {
    let mut p = Processor {
        callback: Some(Box::new(simple_callback)),
    };
    println!("{:?}", p.process_events().err());
    let v = Vector::from(&[1.0, 2.0]);
    let my_fun = move |x: &mut Vector, ksi: &[f64]| {
        println!("using ksi = {:?}", ksi);
        x[0] = v[0];
        x[1] = v[1];
        Ok(())
    };
    // println!("v = {:?}", v);
    p.set_callback(my_fun);
    p.process_events()?;
    Ok(())
}
<commit_msg>Use generics for args in callbacks study<commit_after>use gemlab::util::PI;
use gemlab::StrError;
use russell_lab::Vector;

struct Processor<'a, T> {
    callback: Option<Box<dyn Fn(&mut Vector, &[f64], &T) -> Result<(), StrError> + 'a>>,
}

impl<'a, T> Processor<'a, T> {
    fn set_callback(&mut self, c: impl Fn(&mut Vector, &[f64], &T) -> Result<(), StrError> + 'a) {
        self.callback = Some(Box::new(c));
    }

    fn process_events(&self, args: &T) -> Result<(), StrError> {
        let ksi = vec![0.0; 2];
        let mut x = Vector::new(2);
        match &self.callback {
            Some(cb) => cb(&mut x, &ksi, args)?,
            None => (),
        }
        println!("got x =\n{}", x);
        Ok(())
    }
}

fn simple_callback<T>(_: &mut Vector, _: &[f64], _: &T) -> Result<(), StrError> {
    Err("nothing to see here")
}

pub struct NaturalToReal {
    pub rmin: f64,
    pub rmax: f64,
    pub amin: f64,
    pub amax: f64,
    pub zmin: f64,
    pub zmax: f64,
}

impl NaturalToReal {
    pub fn new() -> Self {
        NaturalToReal {
            rmin: 5.0,
            rmax: 10.0,
            amin: 30.0 * PI / 180.0,
            amax: 60.0 * PI / 180.0,
            zmin: 0.0,
            zmax: 1.0,
        }
    }
}

pub fn natural_to_real_cylindrical(x: &mut Vector, ksi: &[f64], args: &NaturalToReal) -> Result<(), StrError> {
    if x.dim() != ksi.len() {
        return Err("x.dim() must be equal to ksi.len()");
    }
    const KSI_MIN: f64 = -1.0;
    const KSI_DEL: f64 = 2.0;
    let r = args.rmin + (ksi[0] - KSI_MIN) * (args.rmax - args.rmin) / KSI_DEL;
    let a = args.amin + (ksi[1] - KSI_MIN) * (args.amax - args.amin) / KSI_DEL;
    x[0] = r * f64::cos(a);
    x[1] = r * f64::sin(a);
    if x.dim() == 3 {
        x[2] = args.zmin + (ksi[2] - KSI_MIN) * (args.zmax - args.zmin) / KSI_DEL;
    }
    Ok(())
}

fn main() -> Result<(), StrError> {
    let mut p = Processor {
        callback: Some(Box::new(simple_callback)),
        // callback: None,
    };
    let args = NaturalToReal::new();
    println!("{:?}", p.process_events(&args).err());
    let v = Vector::from(&[1.0, 2.0]);
    let my_fun = move |x: &mut Vector, ksi: &[f64], _: &NaturalToReal| {
        println!("using ksi = {:?}", ksi);
        x[0] = v[0];
        x[1] = v[1];
        Ok(())
    };
    // println!("v = {:?}", v);
    p.set_callback(my_fun);
    p.process_events(&args)?;
    p.set_callback(natural_to_real_cylindrical);
    p.process_events(&args)?;
    Ok(())
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate sdl2;

#[macro_use]
extern crate clap;

pub mod gpu;
pub mod controller;
mod sound;

#[allow(dead_code)]
mod debugger;

extern crate gb;

use std::fs::{File, OpenOptions};
use std::io::Read;
use std::thread;
use std::time::{Duration, Instant};

use gb::Emulator;

use self::controller::{Event, Controller};
use self::debugger::Debugger;
use self::gpu::renderer::Renderer;

#[cfg(test)]
mod tests;

fn open_save_file(rom_name: &str) -> Result<File, String> {
    let mut v: Vec<&str> = rom_name.split('.').collect();
    // If the file does not end with .gb we might be reading garbage,
    // let's bail.
    if v.pop() != Some("gb") {
        return Err(format!("Invalid ROM name: '{}' filename must end with '.gb'.", rom_name));
    }

    // Replace extension with "sav"
    v.push("sav");

    let save_name = v.join(".");

    Ok(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(save_name)
        .unwrap())
}

fn open_rom(rom_name: &str) -> Result<File, String> {
    let f = File::open(rom_name);
    f.map_err(|_| format!("Error: ROM '{}' not found.", rom_name))
}

// Similar to try! but for the main function
macro_rules! bail {
    ($expr : expr) => {
        {
            if $expr.is_err() {
                println!("{}", $expr.unwrap_err());
                return;
            }

            $expr.unwrap()
        }
    }
}

pub fn main() {
    let matches = clap_app!(gbrust =>
        (version: "0.1b")
        (author: "Agi Sferro <agi.novanta@gmail.com>")
        (about: "Yet another DMG emulator written in Rust.")
        (@arg ROM: +required "Selects the ROM to run.")
        (@arg mag: -m --magnification +takes_value "Number of times the screen should be magnified. Default is '3'.")
        (@arg debug: -d --debug "Starts in debug mode.")
    ).get_matches();

    let rom_name = matches.value_of("ROM").unwrap();
    let save_file = bail!(open_save_file(&rom_name));

    let mag = value_t!(matches.value_of("mag"), u32).unwrap_or_else(|e| {
        println!("Invalid magnification: {}", e);
        3
    });

    let mut controller = Controller::new(gb::SCREEN_X as u32 * mag,
                                         gb::SCREEN_Y as u32 * mag);

    let mut emulator;
    {
        let mut rom_bytes = vec![];
        let mut rom = bail!(open_rom(&rom_name));
        rom.read_to_end(&mut rom_bytes);

        emulator = Emulator::from_data(&rom_bytes, 44100.0).unwrap();
    }

    let mut last_update = Instant::now();

    // let mut debugger = Debugger::new();

    if matches.occurrences_of("debug") > 0 {
        // debugger.breakpoint(&mut emulator.cpu);
    }

    let mut natural_speed = true;

    loop {
        // debugger.check_breakpoints(&mut emulator);

        emulator.cpu.next_instruction();

        if emulator.cpu.handler_holder.should_refresh() {
            match controller.check_events(&mut emulator) {
                Event::Quit => break,
                Event::Break => {
                    // debugger.breakpoint(&mut emulator);
                },
                Event::ToggleSpeed => { natural_speed = !natural_speed },
                Event::Continue => {},
            }

            controller.refresh(&mut emulator);
        }

        // debugger.next_instruction(&mut emulator);
    }
}
<commit_msg>Enable save files and debugger for the frontend.<commit_after>#[macro_use]
extern crate glium;
extern crate sdl2;

#[macro_use]
extern crate clap;

pub mod gpu;
pub mod controller;
mod sound;

#[allow(dead_code)]
mod debugger;

extern crate gb;

use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};
use std::thread;
use std::time::{Duration, Instant};

use gb::Emulator;

use self::controller::{Event, Controller};
use self::debugger::Debugger;
use self::gpu::renderer::Renderer;

#[cfg(test)]
mod tests;

fn open_save_file(rom_name: &str) -> Result<File, String> {
    let mut v: Vec<&str> = rom_name.split('.').collect();
    // If the file does not end with .gb we might be reading garbage,
    // let's bail.
    if v.pop() != Some("gb") {
        return Err(format!("Invalid ROM name: '{}' filename must end with '.gb'.", rom_name));
    }

    // Replace extension with "sav"
    v.push("srm");

    let save_name = v.join(".");

    Ok(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(save_name)
        .unwrap())
}

fn open_rom(rom_name: &str) -> Result<File, String> {
    let f = File::open(rom_name);
    f.map_err(|_| format!("Error: ROM '{}' not found.", rom_name))
}

// Similar to try! but for the main function
macro_rules! bail {
    ($expr : expr) => {
        {
            if $expr.is_err() {
                println!("{}", $expr.unwrap_err());
                return;
            }

            $expr.unwrap()
        }
    }
}

pub fn main() {
    let matches = clap_app!(gbrust =>
        (version: "0.1b")
        (author: "Agi Sferro <agi.novanta@gmail.com>")
        (about: "Yet another DMG emulator written in Rust.")
        (@arg ROM: +required "Selects the ROM to run.")
        (@arg mag: -m --magnification +takes_value "Number of times the screen should be magnified. Default is '3'.")
        (@arg debug: -d --debug "Starts in debug mode.")
    ).get_matches();

    let rom_name = matches.value_of("ROM").unwrap();
    let mut save_file = bail!(open_save_file(&rom_name));

    let mag = value_t!(matches.value_of("mag"), u32).unwrap_or_else(|e| {
        println!("Invalid magnification: {}", e);
        3
    });

    let mut controller = Controller::new(gb::SCREEN_X as u32 * mag,
                                         gb::SCREEN_Y as u32 * mag);

    let mut emulator;
    {
        let mut rom_bytes = vec![];
        let mut rom = bail!(open_rom(&rom_name));
        rom.read_to_end(&mut rom_bytes).unwrap();

        emulator = Emulator::from_data(&rom_bytes, 44100.0).unwrap();

        // Load save file in ram
        save_file.read_exact(emulator.cpu.handler_holder.ram());
    }

    let mut debugger = Debugger::new();

    if matches.occurrences_of("debug") > 0 {
        debugger.breakpoint(&mut emulator);
    }

    let mut natural_speed = true;

    loop {
        debugger.check_breakpoints(&mut emulator);

        emulator.cpu.next_instruction();

        if emulator.cpu.handler_holder.should_refresh() {
            match controller.check_events(&mut emulator) {
                Event::Quit => break,
                Event::Break => {
                    debugger.breakpoint(&mut emulator);
                },
                Event::ToggleSpeed => { natural_speed = !natural_speed },
                Event::Continue => {},
            }

            controller.refresh(&mut emulator);
        }

        debugger.next_instruction(&mut emulator);
    }

    save_file.seek(SeekFrom::Start(0));
    save_file.write_all(emulator.cpu.handler_holder.ram());
}
<|endoftext|>


<commit_before>use serde_json;

use ::error::*;
use ::Dropbox;
use ::models::files::*;
use ::models::error::*;

pub struct DropboxFiles<'a>
{
	dropbox: &'a Dropbox,
}

impl<'a> DropboxFiles<'a>
{
	pub fn new(dropbox: &'a Dropbox)
	-> Result<DropboxFiles<'a>>
	{
		Ok(DropboxFiles
		{
			dropbox: dropbox,
		})
	}

	/// PREVIEW - may change or disappear without notice
	pub fn alpha_get_metadata()
	-> Result<()>
	{
		Err(DropboxError::Other)
	}

	/// PREVIEW - may change or disappear without notice
	pub fn alpha_upload()
	-> Result<()>
	{
		Err(DropboxError::Other)
	}

	pub fn copy(&self, arg: RelocationArg)
	-> Result<Metadata>
	{
		let uri = gen_uri!("files", "copy");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<Metadata>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<RelocationError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::RelocationError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_batch(&self, arg: RelocationBatchArg)
	-> Result<RelocationBatchLaunch>
	{
		let uri = gen_uri!("files", "copy_batch");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<RelocationBatchLaunch>(&resp)
		{
			Err(_) => Err(DropboxError::Other),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_batch_check(&self, arg: PollArg)
	-> Result<RelocationBatchJobStatus>
	{
		let uri = gen_uri!("files", "copy");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<RelocationBatchJobStatus>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<PollError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::PollError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_reference_get(&self, arg: GetCopyReferenceArg)
	-> Result<GetCopyReferenceResult>
	{
		let uri = gen_uri!("files", "copy_reference", "get");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<GetCopyReferenceResult>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<GetCopyReferenceError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::GetCopyReferenceError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_reference_save(&self, arg: SaveCopyReferenceArg)
	-> Result<SaveCopyReferenceResult>
	{
		let uri = gen_uri!("files", "copy_reference", "save");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<SaveCopyReferenceResult>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<SaveCopyReferenceError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::SaveCopyReferenceError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn create_folder(&self, arg: CreateFolderArg)
	-> Result<FolderMetadata>
	{
		let uri = gen_uri!("files", "create_folder");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<FolderMetadata>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<CreateFolderError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::CreateFolderError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn delete(&self, arg: DeleteArg)
	-> Result<Metadata>
	{
		let uri = gen_uri!("files", "delete");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<Metadata>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<DeleteError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::DeleteError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn delete_batch(&self, arg: DeleteBatchArg)
	-> Result<DeleteBatchLaunch>
	{
		let uri = gen_uri!("files", "delete_batch");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<DeleteBatchLaunch>(&resp)
		{
			Err(_) => Err(DropboxError::Other),
			Ok(r) => Ok(r),
		}
	}

	pub fn delete_batch_check(&self, arg: PollArg)
	-> Result<DeleteBatchJobStatus>
	{
		let uri = gen_uri!("files", "delete_batch", "check");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<DeleteBatchJobStatus>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<PollError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::PollError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn download(&self, arg: DownloadArg)
	-> Result<(FileMetadata, Vec<u8>)>
	{
		let uri = gen_upload_uri!("files", "download");
		let body: String = serde_json::to_string(&arg)?;
		let (file_info, buffer) = self.dropbox.download(uri, body)?;
		let file_info: FileMetadata = match serde_json::from_str::<FileMetadata>(&file_info)
		{
			Err(_) => return Err(DropboxError::Other),
			Ok(r) => r,
		};
		Ok((file_info, buffer))
	}

	pub fn get_metadata()
	{
		unimplemented!();
	}

	pub fn get_preview()
	{
		unimplemented!();
	}

	pub fn get_temporary_link()
	{
		unimplemented!();
	}

	pub fn get_thumbnail()
	{
		unimplemented!();
	}

	pub fn list_folder(&self, arg: ListFolderArg)
	-> Result<ListFolderResult>
	{
		let uri = gen_uri!("files", "list_folder");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<ListFolderResult>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<ListFolderError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::ListFolderError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn list_folders_continue()
	{
		unimplemented!();
	}

	pub fn list_folder_get_lates_cursor()
	{
		unimplemented!();
	}

	pub fn list_folder_longpoll()
	{
		unimplemented!();
	}

	pub fn list_revisions()
	{
		unimplemented!();
	}

	pub fn _move()
	{
		unimplemented!();
	}

	pub fn move_batch()
	{
		unimplemented!();
	}

	pub fn move_batch_check()
	{
		unimplemented!();
	}

	pub fn permanetly_delete()
	{
		unimplemented!();
	}

	pub fn properties_add()
	{
		unimplemented!();
	}

	pub fn properties_overwride()
	{
		unimplemented!();
	}

	pub fn properties_remove()
	{
		unimplemented!();
	}

	pub fn properties_template_get()
	{
		unimplemented!();
	}

	pub fn properties_template_list()
	{
		unimplemented!();
	}

	pub fn properties_update()
	{
		unimplemented!();
	}

	pub fn restore()
	{
		unimplemented!();
	}

	pub fn save_url()
	{
		unimplemented!();
	}

	pub fn save_url_check_jobstatus()
	{
		unimplemented!();
	}

	pub fn search()
	{
		unimplemented!();
	}

	pub fn _upload()
	{
		unimplemented!();
	}

	pub fn upload_session_append()
	{
		unimplemented!();
	}

	pub fn upload_session_apped_v2()
	{
		unimplemented!();
	}

	pub fn upload_session_finish()
	{
		unimplemented!();
	}

	pub fn upload_session_finish_batch()
	{
		unimplemented!();
	}

	pub fn upload_session_finish_batch_check()
	{
		unimplemented!();
	}

	pub fn upload_session_start()
	{
		unimplemented!();
	}
}
<commit_msg>added missing DownloadError<commit_after>use serde_json;

use ::error::*;
use ::Dropbox;
use ::models::files::*;
use ::models::error::*;

pub struct DropboxFiles<'a>
{
	dropbox: &'a Dropbox,
}

impl<'a> DropboxFiles<'a>
{
	pub fn new(dropbox: &'a Dropbox)
	-> Result<DropboxFiles<'a>>
	{
		Ok(DropboxFiles
		{
			dropbox: dropbox,
		})
	}

	/// PREVIEW - may change or disappear without notice
	pub fn alpha_get_metadata()
	-> Result<()>
	{
		Err(DropboxError::Other)
	}

	/// PREVIEW - may change or disappear without notice
	pub fn alpha_upload()
	-> Result<()>
	{
		Err(DropboxError::Other)
	}

	pub fn copy(&self, arg: RelocationArg)
	-> Result<Metadata>
	{
		let uri = gen_uri!("files", "copy");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<Metadata>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<RelocationError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::RelocationError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_batch(&self, arg: RelocationBatchArg)
	-> Result<RelocationBatchLaunch>
	{
		let uri = gen_uri!("files", "copy_batch");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<RelocationBatchLaunch>(&resp)
		{
			Err(_) => Err(DropboxError::Other),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_batch_check(&self, arg: PollArg)
	-> Result<RelocationBatchJobStatus>
	{
		let uri = gen_uri!("files", "copy");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<RelocationBatchJobStatus>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<PollError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::PollError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_reference_get(&self, arg: GetCopyReferenceArg)
	-> Result<GetCopyReferenceResult>
	{
		let uri = gen_uri!("files", "copy_reference", "get");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<GetCopyReferenceResult>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<GetCopyReferenceError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::GetCopyReferenceError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn copy_reference_save(&self, arg: SaveCopyReferenceArg)
	-> Result<SaveCopyReferenceResult>
	{
		let uri = gen_uri!("files", "copy_reference", "save");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<SaveCopyReferenceResult>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<SaveCopyReferenceError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::SaveCopyReferenceError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn create_folder(&self, arg: CreateFolderArg)
	-> Result<FolderMetadata>
	{
		let uri = gen_uri!("files", "create_folder");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<FolderMetadata>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<CreateFolderError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::CreateFolderError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn delete(&self, arg: DeleteArg)
	-> Result<Metadata>
	{
		let uri = gen_uri!("files", "delete");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<Metadata>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<DeleteError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::DeleteError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn delete_batch(&self, arg: DeleteBatchArg)
	-> Result<DeleteBatchLaunch>
	{
		let uri = gen_uri!("files", "delete_batch");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<DeleteBatchLaunch>(&resp)
		{
			Err(_) => Err(DropboxError::Other),
			Ok(r) => Ok(r),
		}
	}

	pub fn delete_batch_check(&self, arg: PollArg)
	-> Result<DeleteBatchJobStatus>
	{
		let uri = gen_uri!("files", "delete_batch", "check");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<DeleteBatchJobStatus>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<PollError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::PollError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn download(&self, arg: DownloadArg)
	-> Result<(FileMetadata, Vec<u8>)>
	{
		let uri = gen_upload_uri!("files", "download");
		let body: String = serde_json::to_string(&arg)?;
		let (file_info, buffer) = self.dropbox.download(uri, body)?;
		let file_info: FileMetadata = match serde_json::from_str::<FileMetadata>(&file_info)
		{
			Err(_) => return Err(match serde_json::from_str::<Error<DownloadError>>(&file_info)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::DownloadError(r),
			}),
			Ok(r) => r,
		};
		Ok((file_info, buffer))
	}

	pub fn get_metadata()
	{
		unimplemented!();
	}

	pub fn get_preview()
	{
		unimplemented!();
	}

	pub fn get_temporary_link()
	{
		unimplemented!();
	}

	pub fn get_thumbnail()
	{
		unimplemented!();
	}

	pub fn list_folder(&self, arg: ListFolderArg)
	-> Result<ListFolderResult>
	{
		let uri = gen_uri!("files", "list_folder");
		let body: String = serde_json::to_string(&arg)?;
		let resp: String = self.dropbox.send_request(uri, body)?;
		match serde_json::from_str::<ListFolderResult>(&resp)
		{
			Err(_) => Err(match serde_json::from_str::<Error<ListFolderError>>(&resp)
			{
				Err(_) => DropboxError::Other,
				Ok(r) => DropboxError::ListFolderError(r),
			}),
			Ok(r) => Ok(r),
		}
	}

	pub fn list_folders_continue()
	{
		unimplemented!();
	}

	pub fn list_folder_get_lates_cursor()
	{
		unimplemented!();
	}

	pub fn list_folder_longpoll()
	{
		unimplemented!();
	}

	pub fn list_revisions()
	{
		unimplemented!();
	}

	pub fn _move()
	{
		unimplemented!();
	}

	pub fn move_batch()
	{
		unimplemented!();
	}

	pub fn move_batch_check()
	{
		unimplemented!();
	}

	pub fn permanetly_delete()
	{
		unimplemented!();
	}

	pub fn properties_add()
	{
		unimplemented!();
	}

	pub fn properties_overwride()
	{
		unimplemented!();
	}

	pub fn properties_remove()
	{
		unimplemented!();
	}

	pub fn properties_template_get()
	{
		unimplemented!();
	}

	pub fn properties_template_list()
	{
		unimplemented!();
	}

	pub fn properties_update()
	{
		unimplemented!();
	}

	pub fn restore()
	{
		unimplemented!();
	}

	pub fn save_url()
	{
		unimplemented!();
	}

	pub fn save_url_check_jobstatus()
	{
		unimplemented!();
	}

	pub fn search()
	{
		unimplemented!();
	}

	pub fn _upload()
	{
		unimplemented!();
	}

	pub fn upload_session_append()
	{
		unimplemented!();
	}

	pub fn upload_session_apped_v2()
	{
		unimplemented!();
	}

	pub fn upload_session_finish()
	{
		unimplemented!();
	}

	pub fn upload_session_finish_batch()
	{
		unimplemented!();
	}

	pub fn upload_session_finish_batch_check()
	{
		unimplemented!();
	}

	pub fn upload_session_start()
	{
		unimplemented!();
	}
}
<|endoftext|>