<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//! > to refer to other crates' documentations.
//!
//! > 🛈 For internal consistency, ruma uses American spelling for variable names. Actual values may
//! > differ, as the matrix specification has a mix of British and American English.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//!   deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-mscXXXX`, where `XXXX` is the MSC number -- Upcoming Matrix features that may be
//!   subject to change or removal.
//! * `unstable-pre-spec` -- Undocumented Matrix features that may be subject to change or removal.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! # `ruma-client` features
//!
//! The `client` feature activates [`ruma::client`][client], and `client-ext-client-api` activates
//! `ruma-client`s `client-api` feature. All other `client-*` features activate the same feature
//! without the `client-` prefix on `ruma-client`. See the crate's documentation for the effect of
//! these features.
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[cfg(feature = "client")]
#[doc(inline)]
pub use ruma_client as client;
#[cfg(feature = "events")]
#[doc(inline)]
pub use ruma_common::events;
#[cfg(feature = "signatures")]
#[doc(inline)]
pub use ruma_signatures as signatures;
#[cfg(feature = "state-res")]
#[doc(inline)]
pub use ruma_state_res as state_res;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://spec.matrix.org/v1.2/#matrix-apis
#[cfg(feature = "api")]
pub mod api {
    pub use ruma_common::api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};
#[cfg(feature = "client-ext-client-api")]
pub use ruma_client::Client;
pub use ruma_common::{
    authentication, device_id, device_key_id, directory, encryption, event_id, exports, matrix_uri,
    mxc_uri, power_levels, presence, push, receipt, room, room_alias_id, room_id, room_version_id,
    serde, server_name, server_signing_key_id, thirdparty, to_device, user_id, ClientSecret,
    DeviceId, DeviceKeyAlgorithm, DeviceKeyId, DeviceSignatures, DeviceSigningKeyId,
    EntitySignatures, EventEncryptionAlgorithm, EventId, IdParseError, KeyId, KeyName, MatrixToUri,
    MatrixUri, MilliSecondsSinceUnixEpoch, MxcUri, OwnedClientSecret, OwnedDeviceId,
    OwnedDeviceKeyId, OwnedDeviceSigningKeyId, OwnedEventId, OwnedKeyId, OwnedKeyName, OwnedMxcUri,
    OwnedRoomAliasId, OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, OwnedServerSigningKeyId,
    OwnedSessionId, OwnedSigningKeyId, OwnedTransactionId, OwnedUserId, PrivOwnedStr, RoomAliasId,
    RoomId, RoomOrAliasId, RoomVersionId, SecondsSinceUnixEpoch, ServerName, ServerSignatures,
    ServerSigningKeyId, SessionId, Signatures, SigningKeyAlgorithm, TransactionId, UserId,
};
<commit_msg>ruma: Re-export canonical_json module and related types<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//! > to refer to other crates' documentations.
//!
//! > 🛈 For internal consistency, ruma uses American spelling for variable names. Actual values may
//! > differ, as the matrix specification has a mix of British and American English.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//!   deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-mscXXXX`, where `XXXX` is the MSC number -- Upcoming Matrix features that may be
//!   subject to change or removal.
//! * `unstable-pre-spec` -- Undocumented Matrix features that may be subject to change or removal.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! # `ruma-client` features
//!
//! The `client` feature activates [`ruma::client`][client], and `client-ext-client-api` activates
//! `ruma-client`s `client-api` feature. All other `client-*` features activate the same feature
//! without the `client-` prefix on `ruma-client`. See the crate's documentation for the effect of
//! these features.
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[cfg(feature = "client")]
#[doc(inline)]
pub use ruma_client as client;
#[cfg(feature = "events")]
#[doc(inline)]
pub use ruma_common::events;
#[cfg(feature = "signatures")]
#[doc(inline)]
pub use ruma_signatures as signatures;
#[cfg(feature = "state-res")]
#[doc(inline)]
pub use ruma_state_res as state_res;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://spec.matrix.org/v1.2/#matrix-apis
#[cfg(feature = "api")]
pub mod api {
    pub use ruma_common::api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};
#[cfg(feature = "client-ext-client-api")]
pub use ruma_client::Client;
pub use ruma_common::{
    authentication, device_id, device_key_id, directory, encryption, event_id, exports, matrix_uri,
    mxc_uri, power_levels, presence, push, receipt, room, room_alias_id, room_id, room_version_id,
    serde, server_name, server_signing_key_id, thirdparty, to_device, user_id, ClientSecret,
    DeviceId, DeviceKeyAlgorithm, DeviceKeyId, DeviceSignatures, DeviceSigningKeyId,
    EntitySignatures, EventEncryptionAlgorithm, EventId, IdParseError, KeyId, KeyName, MatrixToUri,
    MatrixUri, MilliSecondsSinceUnixEpoch, MxcUri, OwnedClientSecret, OwnedDeviceId,
    OwnedDeviceKeyId, OwnedDeviceSigningKeyId, OwnedEventId, OwnedKeyId, OwnedKeyName, OwnedMxcUri,
    OwnedRoomAliasId, OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, OwnedServerSigningKeyId,
    OwnedSessionId, OwnedSigningKeyId, OwnedTransactionId, OwnedUserId, PrivOwnedStr, RoomAliasId,
    RoomId, RoomOrAliasId, RoomVersionId, SecondsSinceUnixEpoch, ServerName, ServerSignatures,
    ServerSigningKeyId, SessionId, Signatures, SigningKeyAlgorithm, TransactionId, UserId,
};
#[cfg(feature = "canonical-json")]
pub use ruma_common::{
    canonical_json, CanonicalJsonError, CanonicalJsonObject, CanonicalJsonValue,
};
<|endoftext|>


<commit_before>//! Manager that is called when a seat is created or destroyed.
//! Pass a struct that implements this trait to the `Compositor` during
//! initialization.

use super::{KeyboardHandler, KeyboardWrapper, PointerHandler, PointerWrapper};
use libc;
use std::env;
use types::input_device::InputDevice;
use utils::safe_as_cstring;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wlr_input_device, wlr_input_device_type, wlr_keyboard_set_keymap,
                  xkb_context_new, xkb_context_unref, xkb_keymap_new_from_names, xkb_rule_names};
use wlroots_sys::xkb_context_flags::*;
use wlroots_sys::xkb_keymap_compile_flags::*;

/// Different type of inputs that can be acquired.
pub enum Input {
    Keyboard(Box<KeyboardWrapper>),
    Pointer(Box<PointerWrapper>)
}

impl Input {
    pub fn input_device(&self) -> &InputDevice {
        use self::Input::*;
        match *self {
            Keyboard(ref keyboard) => keyboard.input_device(),
            Pointer(ref pointer) => pointer.input_device(),
        }
    }
}

/// Handles input addition and removal.
pub trait InputManagerHandler {
    /// Callback triggered when an input device is added.
    fn input_added(&mut self, &mut InputDevice) {}

    /// Callback triggered when an input device is removed.
    fn input_removed(&mut self, &mut InputDevice) {
        // TODO
    }

    fn keyboard_added(&mut self, &mut InputDevice) -> Option<Box<KeyboardHandler>> {
        None
    }

    fn pointer_added(&mut self, &mut InputDevice) -> Option<Box<PointerHandler>> {
        None
    }
}

wayland_listener!(InputManager, (Vec<Input>, Box<InputManagerHandler>), [
    add_listener => add_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut inputs, ref mut manager) = this.data;
        use self::wlr_input_device_type::*;
        let mut dev = InputDevice::from_ptr(data as *mut wlr_input_device);
        unsafe {
            match dev.dev_type() {
                WLR_INPUT_DEVICE_KEYBOARD => {
                    // Boring setup that we won't make the user do
                    add_keyboard(&mut dev);
                    // Get the optional user keyboard struct, add the on_key signal
                    if let Some(keyboard_handler) = manager.keyboard_added(&mut dev) {
                        let dev_ = InputDevice::from_ptr(data as *mut wlr_input_device);
                        let mut keyboard = KeyboardWrapper::new((dev_, keyboard_handler));
                        wl_signal_add(&mut (*dev.dev_union().keyboard).events.key as *mut _ as _,
                                    keyboard.key_listener() as *mut _ as _);
                        // Forget until we need to drop it in the destroy callback
                        inputs.push(Input::Keyboard(keyboard));
                    }
                },
                WLR_INPUT_DEVICE_POINTER => {
                    // Get the optional user pointer struct, add the signals
                    if let Some(pointer) = manager.pointer_added(&mut dev) {
                        let dev_ = InputDevice::from_ptr(data as *mut wlr_input_device);
                        let mut pointer = PointerWrapper::new((dev_, pointer));
                        wl_signal_add(&mut (*dev.dev_union().pointer).events.motion as *mut _ as _,
                                    pointer.motion_listener() as *mut _ as _);
                        wl_signal_add(&mut (*dev.dev_union().pointer)
                                      .events.motion_absolute as *mut _ as _,
                                    pointer.motion_absolute_listener() as *mut _ as _);
                        wl_signal_add(&mut (*dev.dev_union().pointer).events.button as *mut _ as _,
                                    pointer.button_listener() as *mut _ as _);
                        wl_signal_add(&mut (*dev.dev_union().pointer).events.axis as *mut _ as _,
                                    pointer.axis_listener() as *mut _ as _);
                        // Forget until we need to drop it in the destroy callback
                        inputs.push(Input::Pointer(pointer))
                    }
                },
                _ => unimplemented!(), // TODO FIXME We _really_ shouldn't panic here
            }
        }
        manager.input_added(&mut dev)
    };
    remove_listener => remove_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut inputs, ref mut manager) = this.data;
        manager.input_removed(&mut InputDevice::from_ptr(data as *mut wlr_input_device));
        // Remove user output data
        let find_index = inputs.iter()
            .position(|input| input.input_device().to_ptr() == data as _);
        if let Some(index) = find_index {
            let removed_input = inputs.remove(index);
            match removed_input {
                Input::Keyboard(mut keyboard) => {
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*keyboard.key_listener()).link as *mut _ as _);
                },
                Input::Pointer(mut pointer) => {
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.button_listener()).link as *mut _ as _);
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.motion_listener()).link as *mut _ as _);
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.motion_absolute_listener()).link as *mut _ as _);
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.axis_listener()).link as *mut _ as _);
                }
            }
        }
    };
]);

pub unsafe fn add_keyboard(dev: &mut InputDevice) {
    // Set the XKB settings
    let rules = safe_as_cstring(env::var("XKB_DEFAULT_RULES").unwrap_or("".into()));
    let model = safe_as_cstring(env::var("XKB_DEFAULT_MODEL").unwrap_or("".into()));
    let layout = safe_as_cstring(env::var("XKB_DEFAULT_LAYOUT").unwrap_or("".into()));
    let variant = safe_as_cstring(env::var("XKB_DEFAULT_VARIANT").unwrap_or("".into()));
    let options = safe_as_cstring(env::var("XKB_DEFAULT_OPTIONS").unwrap_or("".into()));
    let rules = xkb_rule_names {
        rules: rules.into_raw(),
        model: model.into_raw(),
        layout: layout.into_raw(),
        variant: variant.into_raw(),
        options: options.into_raw()
    };
    let context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
    if context.is_null() {
        wlr_log!(L_ERROR, "Failed to create XKB context");
        // NOTE We don't panic here, because we have a C call stack above us
        ::std::process::exit(1)
    }
    let xkb_map = xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
    wlr_keyboard_set_keymap(dev.dev_union().keyboard, xkb_map);
    xkb_context_unref(context);
}
<commit_msg>Added TODO comment<commit_after>//! Manager that is called when a seat is created or destroyed.
//! Pass a struct that implements this trait to the `Compositor` during
//! initialization.

use super::{KeyboardHandler, KeyboardWrapper, PointerHandler, PointerWrapper};
use libc;
use std::env;
use types::input_device::InputDevice;
use utils::safe_as_cstring;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wlr_input_device, wlr_input_device_type, wlr_keyboard_set_keymap,
                  xkb_context_new, xkb_context_unref, xkb_keymap_new_from_names, xkb_rule_names};
use wlroots_sys::xkb_context_flags::*;
use wlroots_sys::xkb_keymap_compile_flags::*;

/// Different type of inputs that can be acquired.
pub enum Input {
    Keyboard(Box<KeyboardWrapper>),
    Pointer(Box<PointerWrapper>)
}

impl Input {
    // TODO FIXME This isn't really safe...
    // Make these instead store the types/ ones
    // e.g Keyboard(types::Keyboard)
    // For one thing all we need is the dev pointers...
    pub fn input_device(&self) -> &InputDevice {
        use self::Input::*;
        match *self {
            Keyboard(ref keyboard) => keyboard.input_device(),
            Pointer(ref pointer) => pointer.input_device(),
        }
    }
}

/// Handles input addition and removal.
pub trait InputManagerHandler {
    /// Callback triggered when an input device is added.
    fn input_added(&mut self, &mut InputDevice) {}

    /// Callback triggered when an input device is removed.
    fn input_removed(&mut self, &mut InputDevice) {
        // TODO
    }

    fn keyboard_added(&mut self, &mut InputDevice) -> Option<Box<KeyboardHandler>> {
        None
    }

    fn pointer_added(&mut self, &mut InputDevice) -> Option<Box<PointerHandler>> {
        None
    }
}

wayland_listener!(InputManager, (Vec<Input>, Box<InputManagerHandler>), [
    add_listener => add_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut inputs, ref mut manager) = this.data;
        use self::wlr_input_device_type::*;
        let mut dev = InputDevice::from_ptr(data as *mut wlr_input_device);
        unsafe {
            match dev.dev_type() {
                WLR_INPUT_DEVICE_KEYBOARD => {
                    // Boring setup that we won't make the user do
                    add_keyboard(&mut dev);
                    // Get the optional user keyboard struct, add the on_key signal
                    if let Some(keyboard_handler) = manager.keyboard_added(&mut dev) {
                        let dev_ = InputDevice::from_ptr(data as *mut wlr_input_device);
                        let mut keyboard = KeyboardWrapper::new((dev_, keyboard_handler));
                        wl_signal_add(&mut (*dev.dev_union().keyboard).events.key as *mut _ as _,
                                    keyboard.key_listener() as *mut _ as _);
                        // Forget until we need to drop it in the destroy callback
                        inputs.push(Input::Keyboard(keyboard));
                    }
                },
                WLR_INPUT_DEVICE_POINTER => {
                    // Get the optional user pointer struct, add the signals
                    if let Some(pointer) = manager.pointer_added(&mut dev) {
                        let dev_ = InputDevice::from_ptr(data as *mut wlr_input_device);
                        let mut pointer = PointerWrapper::new((dev_, pointer));
                        wl_signal_add(&mut (*dev.dev_union().pointer).events.motion as *mut _ as _,
                                    pointer.motion_listener() as *mut _ as _);
                        wl_signal_add(&mut (*dev.dev_union().pointer)
                                      .events.motion_absolute as *mut _ as _,
                                    pointer.motion_absolute_listener() as *mut _ as _);
                        wl_signal_add(&mut (*dev.dev_union().pointer).events.button as *mut _ as _,
                                    pointer.button_listener() as *mut _ as _);
                        wl_signal_add(&mut (*dev.dev_union().pointer).events.axis as *mut _ as _,
                                    pointer.axis_listener() as *mut _ as _);
                        // Forget until we need to drop it in the destroy callback
                        inputs.push(Input::Pointer(pointer))
                    }
                },
                _ => unimplemented!(), // TODO FIXME We _really_ shouldn't panic here
            }
        }
        manager.input_added(&mut dev)
    };
    remove_listener => remove_notify: |this: &mut InputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut inputs, ref mut manager) = this.data;
        manager.input_removed(&mut InputDevice::from_ptr(data as *mut wlr_input_device));
        // Remove user output data
        let find_index = inputs.iter()
            .position(|input| input.input_device().to_ptr() == data as _);
        if let Some(index) = find_index {
            let removed_input = inputs.remove(index);
            match removed_input {
                Input::Keyboard(mut keyboard) => {
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*keyboard.key_listener()).link as *mut _ as _);
                },
                Input::Pointer(mut pointer) => {
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.button_listener()).link as *mut _ as _);
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.motion_listener()).link as *mut _ as _);
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.motion_absolute_listener()).link as *mut _ as _);
                    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                  wl_list_remove,
                                  &mut (*pointer.axis_listener()).link as *mut _ as _);
                }
            }
        }
    };
]);

pub unsafe fn add_keyboard(dev: &mut InputDevice) {
    // Set the XKB settings
    let rules = safe_as_cstring(env::var("XKB_DEFAULT_RULES").unwrap_or("".into()));
    let model = safe_as_cstring(env::var("XKB_DEFAULT_MODEL").unwrap_or("".into()));
    let layout = safe_as_cstring(env::var("XKB_DEFAULT_LAYOUT").unwrap_or("".into()));
    let variant = safe_as_cstring(env::var("XKB_DEFAULT_VARIANT").unwrap_or("".into()));
    let options = safe_as_cstring(env::var("XKB_DEFAULT_OPTIONS").unwrap_or("".into()));
    let rules = xkb_rule_names {
        rules: rules.into_raw(),
        model: model.into_raw(),
        layout: layout.into_raw(),
        variant: variant.into_raw(),
        options: options.into_raw()
    };
    let context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
    if context.is_null() {
        wlr_log!(L_ERROR, "Failed to create XKB context");
        // NOTE We don't panic here, because we have a C call stack above us
        ::std::process::exit(1)
    }
    let xkb_map = xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
    wlr_keyboard_set_keymap(dev.dev_union().keyboard, xkb_map);
    xkb_context_unref(context);
}
<|endoftext|>


<commit_before>// Third attempt.

use mio::{self, unix, Ready};
use mio::unix::UnixReady;
use std::io;
use dbus::{Connection, ConnectionItems, ConnectionItem, Watch, WatchEvent, Message, Error as DBusError};
use futures::{Async, Future, Stream, Poll};
use futures::sync::{oneshot, mpsc};
use tokio_core::reactor::{PollEvented, Handle as CoreHandle};
use std::rc::Rc;
use std::os::raw::c_uint;
use std::cell::RefCell;
use std::collections::HashMap;
use std::os::unix::io::RawFd;

type MCallMap = Rc<RefCell<HashMap<u32, oneshot::Sender<Message>>>>;

type MStream = Rc<RefCell<Option<mpsc::UnboundedSender<Message>>>>;

#[derive(Debug)]
/// A Tokio enabled D-Bus connection.
///
/// While an AConnection exists, it will consume all incoming messages.
/// Creating more than one AConnection for the same Connection is not recommended.
pub struct AConnection {
    conn: Rc<Connection>,
    quit: Option<oneshot::Sender<()>>,
    callmap: MCallMap,
    msgstream: MStream,
}

impl AConnection {
    /// Create an AConnection, which spawns a task on the core.
    ///
    /// The task handles incoming messages, and continues to do so until the
    /// AConnection is dropped.
    pub fn new(c: Rc<Connection>, h: CoreHandle) -> io::Result<AConnection> {
        let (tx, rx) = oneshot::channel();
        let map: MCallMap = Default::default();
        let istream: MStream = Default::default();
        let mut d = ADriver {
            conn: c.clone(),
            fds: HashMap::new(),
            core: h.clone(),
            quit: rx,
            callmap: map.clone(),
            msgstream: istream.clone(),
        };
        let i = AConnection {
            conn: c,
            quit: Some(tx),
            callmap: map,
            msgstream: istream,
        };
        for w in i.conn.watch_fds() { d.modify_watch(w)?; }
        h.spawn(d);
        Ok(i)
    }

    /// Sends a method call message, and returns a Future for the method return.
    pub fn method_call(&self, m: Message) -> Result<AMethodCall, &'static str> {
        let r = self.conn.send(m).map_err(|_| "D-Bus send error")?;
        let (tx, rx) = oneshot::channel();
        let mut map = self.callmap.borrow_mut();
        map.insert(r, tx); // TODO: error check for duplicate entries. Should not happen, but if it does...
        let mc = AMethodCall { serial: r, callmap: self.callmap.clone(), inner: rx };
        Ok(mc)
    }

    /// Returns a stream of incoming messages.
    ///
    /// Creating more than one stream for the same AConnection is not supported; this function will
    /// fail with an error if you try. Drop the first stream if you need to create a second one.
    pub fn messages(&self) -> Result<AMessageStream, &'static str> {
        let mut i = self.msgstream.borrow_mut();
        if i.is_some() { return Err("Another instance of AMessageStream already exists"); }
        let (tx, rx) = mpsc::unbounded();
        *i = Some(tx);
        Ok(AMessageStream { inner: rx, stream: self.msgstream.clone() })
    }
}

impl Drop for AConnection {
    fn drop(&mut self) { let _ = self.quit.take().unwrap().send(()); }
}

#[derive(Debug)]
// Internal struct; this is the future spawned on the core.
struct ADriver {
    conn: Rc<Connection>,
    fds: HashMap<RawFd, PollEvented<AWatch>>,
    core: CoreHandle,
    quit: oneshot::Receiver<()>,
    callmap: MCallMap,
    msgstream: MStream,
}

impl ADriver {
    fn modify_watch(&mut self, w: Watch) -> io::Result<()> {
        if !w.readable() && !w.writable() {
            self.fds.remove(&w.fd());
        } else {

            if let Some(evented) = self.fds.get(&w.fd()) {
                let ww = evented.get_ref().0;
                if ww.readable() == w.readable() || ww.readable() == w.readable() { return Ok(()) };
            }
            self.fds.remove(&w.fd());

            let z = PollEvented::new(AWatch(w), &self.core)?;

            self.fds.insert(w.fd(), z);
        }
        Ok(())
    }

    fn send_stream(&self, m: Message) {
        self.msgstream.borrow().as_ref().map(|z| { z.send(m).unwrap() });
    }

    fn handle_items(&mut self, items: ConnectionItems) {
        // TODO: What about all unwrapping in this function
        for i in items {
            // println!("Got: {:?}", i);
            match i {
                ConnectionItem::WatchFd(w) => { self.modify_watch(w).unwrap(); },
                ConnectionItem::MethodReturn(m) => {
                    let mut map = self.callmap.borrow_mut();
                    let serial = m.get_reply_serial().unwrap();
                    let r = map.remove(&serial);
                    if let Some(r) = r { r.send(m).unwrap(); }
                    else { self.send_stream(m) }
                }
                ConnectionItem::Nothing => return,
                ConnectionItem::Signal(m) => self.send_stream(m),
                ConnectionItem::MethodCall(m) => self.send_stream(m),
            }
        }
    }
}

impl Future for ADriver {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Result<Async<()>, ()> {
        let q = self.quit.poll();
        if q != Ok(Async::NotReady) { return Ok(Async::Ready(())); }

        let cc = self.conn.clone(); // Borrow checker made me do this
        let mut items = None;
        for w in self.fds.values() {
            let mut mask = UnixReady::hup() | UnixReady::error();
            if w.get_ref().0.readable() { mask = mask | Ready::readable().into(); }
            if w.get_ref().0.writable() { mask = mask | Ready::writable().into(); }
            let pr = w.poll_ready(*mask);
            // println!("{:?} is {:?}", w.get_ref().0.fd(), pr);
            let ur = if let Async::Ready(t) = pr { UnixReady::from(t) } else { continue };
            let flags =
                if ur.is_readable() { WatchEvent::Readable as c_uint } else { 0 } +
                if ur.is_writable() { WatchEvent::Writable as c_uint } else { 0 } +
                if ur.is_hup() { WatchEvent::Hangup as c_uint } else { 0 } +
                if ur.is_error() { WatchEvent::Error as c_uint } else { 0 };
            // println!("{:?} is {:?}", w.get_ref().0.fd(), ur);
            items = Some(cc.watch_handle(w.get_ref().0.fd(), flags));
            if ur.is_readable() { w.need_read() };
            if ur.is_writable() { w.need_write() };
        };
        self.handle_items(items.unwrap_or(cc.iter(0)));
        Ok(Async::NotReady)
    }
}

#[derive(Debug)]
struct AWatch(Watch);

impl mio::Evented for AWatch {
    fn register(&self,
                poll: &mio::Poll,
                token: mio::Token,
                mut interest: mio::Ready,
                opts: mio::PollOpt) -> io::Result<()>
    {
        if !self.0.readable() { interest.remove(mio::Ready::readable()) };
        if !self.0.writable() { interest.remove(mio::Ready::writable()) };
        unix::EventedFd(&self.0.fd()).register(poll, token, interest, opts)
    }

    fn reregister(&self,
                  poll: &mio::Poll,
                  token: mio::Token,
                  interest: mio::Ready,
                  opts: mio::PollOpt) -> io::Result<()>
    {
        self.register(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        unix::EventedFd(&self.0.fd()).deregister(poll)
    }
}

#[derive(Debug)]
/// A Future that resolves when a method call is replied to.
pub struct AMethodCall {
    serial: u32,
    callmap: MCallMap,
    inner: oneshot::Receiver<Message>,
}

impl Future for AMethodCall {
    type Item = Message;
    type Error = DBusError;

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
        let x = self.inner.poll().map_err(|_| DBusError::new_custom("org.freedesktop.DBus.Failed", "Tokio cancelled future"))?;
        if let Async::Ready(mut m) = x {
            m.as_result()?;
            Ok(Async::Ready(m))
        } else { Ok(Async::NotReady) }
    }
}

impl Drop for AMethodCall {
    fn drop(&mut self) {
        let mut map = self.callmap.borrow_mut();
        map.remove(&self.serial);
    }
}

#[derive(Debug)]
/// A Stream of incoming messages.
///
/// Messages already processed (method returns for AMethodCall, fd changes)
/// are already consumed and will not be present in the stream.
pub struct AMessageStream {
    inner: mpsc::UnboundedReceiver<Message>,
    stream: MStream,
}

impl Stream for AMessageStream {
    type Item = Message;
    type Error = ();
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // println!("Polling message stream");
        let r = self.inner.poll();
        // println!("msgstream {:?}", r);
        r
    }
}

impl Drop for AMessageStream {
    fn drop(&mut self) {
        *self.stream.borrow_mut() = None;
    }
}

#[test]
fn aconnection_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();
    let aconn = AConnection::new(conn.clone(), core.handle()).unwrap();

    let m = ::dbus::Message::new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames").unwrap();
    let reply = core.run(aconn.method_call(m).unwrap()).unwrap();
    let z: Vec<&str> = reply.get1().unwrap();
    println!("got reply: {:?}", z);
    assert!(z.iter().any(|v| *v == "org.freedesktop.DBus"));
}

#[test]
fn astream_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();
    let aconn = AConnection::new(conn.clone(), core.handle()).unwrap();

    let items: AMessageStream = aconn.messages().unwrap();
    let signals = items.filter_map(|m| if m.msg_type() == ::dbus::MessageType::Signal { Some(m) } else { None });
    let firstsig = core.run(signals.into_future()).map(|(x, _)| x).map_err(|(x, _)| x).unwrap();
    println!("first signal was: {:?}", firstsig);
    assert_eq!(firstsig.unwrap().msg_type(), ::dbus::MessageType::Signal);
}

<commit_msg>Call EventedFd::reregister() in AWatch::reregister()<commit_after>// Third attempt.

use mio::{self, unix, Ready};
use mio::unix::UnixReady;
use std::io;
use dbus::{Connection, ConnectionItems, ConnectionItem, Watch, WatchEvent, Message, Error as DBusError};
use futures::{Async, Future, Stream, Poll};
use futures::sync::{oneshot, mpsc};
use tokio_core::reactor::{PollEvented, Handle as CoreHandle};
use std::rc::Rc;
use std::os::raw::c_uint;
use std::cell::RefCell;
use std::collections::HashMap;
use std::os::unix::io::RawFd;

type MCallMap = Rc<RefCell<HashMap<u32, oneshot::Sender<Message>>>>;

type MStream = Rc<RefCell<Option<mpsc::UnboundedSender<Message>>>>;

#[derive(Debug)]
/// A Tokio enabled D-Bus connection.
///
/// While an AConnection exists, it will consume all incoming messages.
/// Creating more than one AConnection for the same Connection is not recommended.
pub struct AConnection {
    conn: Rc<Connection>,
    quit: Option<oneshot::Sender<()>>,
    callmap: MCallMap,
    msgstream: MStream,
}

impl AConnection {
    /// Create an AConnection, which spawns a task on the core.
    ///
    /// The task handles incoming messages, and continues to do so until the
    /// AConnection is dropped.
    pub fn new(c: Rc<Connection>, h: CoreHandle) -> io::Result<AConnection> {
        let (tx, rx) = oneshot::channel();
        let map: MCallMap = Default::default();
        let istream: MStream = Default::default();
        let mut d = ADriver {
            conn: c.clone(),
            fds: HashMap::new(),
            core: h.clone(),
            quit: rx,
            callmap: map.clone(),
            msgstream: istream.clone(),
        };
        let i = AConnection {
            conn: c,
            quit: Some(tx),
            callmap: map,
            msgstream: istream,
        };
        for w in i.conn.watch_fds() { d.modify_watch(w)?; }
        h.spawn(d);
        Ok(i)
    }

    /// Sends a method call message, and returns a Future for the method return.
    pub fn method_call(&self, m: Message) -> Result<AMethodCall, &'static str> {
        let r = self.conn.send(m).map_err(|_| "D-Bus send error")?;
        let (tx, rx) = oneshot::channel();
        let mut map = self.callmap.borrow_mut();
        map.insert(r, tx); // TODO: error check for duplicate entries. Should not happen, but if it does...
        let mc = AMethodCall { serial: r, callmap: self.callmap.clone(), inner: rx };
        Ok(mc)
    }

    /// Returns a stream of incoming messages.
    ///
    /// Creating more than one stream for the same AConnection is not supported; this function will
    /// fail with an error if you try. Drop the first stream if you need to create a second one.
    pub fn messages(&self) -> Result<AMessageStream, &'static str> {
        let mut i = self.msgstream.borrow_mut();
        if i.is_some() { return Err("Another instance of AMessageStream already exists"); }
        let (tx, rx) = mpsc::unbounded();
        *i = Some(tx);
        Ok(AMessageStream { inner: rx, stream: self.msgstream.clone() })
    }
}

impl Drop for AConnection {
    fn drop(&mut self) { let _ = self.quit.take().unwrap().send(()); }
}

#[derive(Debug)]
// Internal struct; this is the future spawned on the core.
struct ADriver {
    conn: Rc<Connection>,
    fds: HashMap<RawFd, PollEvented<AWatch>>,
    core: CoreHandle,
    quit: oneshot::Receiver<()>,
    callmap: MCallMap,
    msgstream: MStream,
}

impl ADriver {
    fn modify_watch(&mut self, w: Watch) -> io::Result<()> {
        if !w.readable() && !w.writable() {
            self.fds.remove(&w.fd());
        } else {

            if let Some(evented) = self.fds.get(&w.fd()) {
                let ww = evented.get_ref().0;
                if ww.readable() == w.readable() || ww.readable() == w.readable() { return Ok(()) };
            }
            self.fds.remove(&w.fd());

            let z = PollEvented::new(AWatch(w), &self.core)?;

            self.fds.insert(w.fd(), z);
        }
        Ok(())
    }

    fn send_stream(&self, m: Message) {
        self.msgstream.borrow().as_ref().map(|z| { z.send(m).unwrap() });
    }

    fn handle_items(&mut self, items: ConnectionItems) {
        // TODO: What about all unwrapping in this function
        for i in items {
            // println!("Got: {:?}", i);
            match i {
                ConnectionItem::WatchFd(w) => { self.modify_watch(w).unwrap(); },
                ConnectionItem::MethodReturn(m) => {
                    let mut map = self.callmap.borrow_mut();
                    let serial = m.get_reply_serial().unwrap();
                    let r = map.remove(&serial);
                    if let Some(r) = r { r.send(m).unwrap(); }
                    else { self.send_stream(m) }
                }
                ConnectionItem::Nothing => return,
                ConnectionItem::Signal(m) => self.send_stream(m),
                ConnectionItem::MethodCall(m) => self.send_stream(m),
            }
        }
    }
}

impl Future for ADriver {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Result<Async<()>, ()> {
        let q = self.quit.poll();
        if q != Ok(Async::NotReady) { return Ok(Async::Ready(())); }

        let cc = self.conn.clone(); // Borrow checker made me do this
        let mut items = None;
        for w in self.fds.values() {
            let mut mask = UnixReady::hup() | UnixReady::error();
            if w.get_ref().0.readable() { mask = mask | Ready::readable().into(); }
            if w.get_ref().0.writable() { mask = mask | Ready::writable().into(); }
            let pr = w.poll_ready(*mask);
            // println!("{:?} is {:?}", w.get_ref().0.fd(), pr);
            let ur = if let Async::Ready(t) = pr { UnixReady::from(t) } else { continue };
            let flags =
                if ur.is_readable() { WatchEvent::Readable as c_uint } else { 0 } +
                if ur.is_writable() { WatchEvent::Writable as c_uint } else { 0 } +
                if ur.is_hup() { WatchEvent::Hangup as c_uint } else { 0 } +
                if ur.is_error() { WatchEvent::Error as c_uint } else { 0 };
            // println!("{:?} is {:?}", w.get_ref().0.fd(), ur);
            items = Some(cc.watch_handle(w.get_ref().0.fd(), flags));
            if ur.is_readable() { w.need_read() };
            if ur.is_writable() { w.need_write() };
        };
        self.handle_items(items.unwrap_or(cc.iter(0)));
        Ok(Async::NotReady)
    }
}

#[derive(Debug)]
struct AWatch(Watch);

impl mio::Evented for AWatch {
    fn register(&self,
                poll: &mio::Poll,
                token: mio::Token,
                mut interest: mio::Ready,
                opts: mio::PollOpt) -> io::Result<()>
    {
        if !self.0.readable() { interest.remove(mio::Ready::readable()) };
        if !self.0.writable() { interest.remove(mio::Ready::writable()) };
        unix::EventedFd(&self.0.fd()).register(poll, token, interest, opts)
    }

    fn reregister(&self,
                  poll: &mio::Poll,
                  token: mio::Token,
                  mut interest: mio::Ready,
                  opts: mio::PollOpt) -> io::Result<()>
    {
        if !self.0.readable() { interest.remove(mio::Ready::readable()) };
        if !self.0.writable() { interest.remove(mio::Ready::writable()) };
        unix::EventedFd(&self.0.fd()).reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        unix::EventedFd(&self.0.fd()).deregister(poll)
    }
}

#[derive(Debug)]
/// A Future that resolves when a method call is replied to.
pub struct AMethodCall {
    serial: u32,
    callmap: MCallMap,
    inner: oneshot::Receiver<Message>,
}

impl Future for AMethodCall {
    type Item = Message;
    type Error = DBusError;

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
        let x = self.inner.poll().map_err(|_| DBusError::new_custom("org.freedesktop.DBus.Failed", "Tokio cancelled future"))?;
        if let Async::Ready(mut m) = x {
            m.as_result()?;
            Ok(Async::Ready(m))
        } else { Ok(Async::NotReady) }
    }
}

impl Drop for AMethodCall {
    fn drop(&mut self) {
        let mut map = self.callmap.borrow_mut();
        map.remove(&self.serial);
    }
}

#[derive(Debug)]
/// A Stream of incoming messages.
///
/// Messages already processed (method returns for AMethodCall, fd changes)
/// are already consumed and will not be present in the stream.
pub struct AMessageStream {
    inner: mpsc::UnboundedReceiver<Message>,
    stream: MStream,
}

impl Stream for AMessageStream {
    type Item = Message;
    type Error = ();
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        // println!("Polling message stream");
        let r = self.inner.poll();
        // println!("msgstream {:?}", r);
        r
    }
}

impl Drop for AMessageStream {
    fn drop(&mut self) {
        *self.stream.borrow_mut() = None;
    }
}

#[test]
fn aconnection_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();
    let aconn = AConnection::new(conn.clone(), core.handle()).unwrap();

    let m = ::dbus::Message::new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames").unwrap();
    let reply = core.run(aconn.method_call(m).unwrap()).unwrap();
    let z: Vec<&str> = reply.get1().unwrap();
    println!("got reply: {:?}", z);
    assert!(z.iter().any(|v| *v == "org.freedesktop.DBus"));
}

#[test]
fn astream_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();
    let aconn = AConnection::new(conn.clone(), core.handle()).unwrap();

    let items: AMessageStream = aconn.messages().unwrap();
    let signals = items.filter_map(|m| if m.msg_type() == ::dbus::MessageType::Signal { Some(m) } else { None });
    let firstsig = core.run(signals.into_future()).map(|(x, _)| x).map_err(|(x, _)| x).unwrap();
    println!("first signal was: {:?}", firstsig);
    assert_eq!(firstsig.unwrap().msg_type(), ::dbus::MessageType::Signal);
}

<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fmt;

use serde::de::{EnumAccess, Error, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer};

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Enum(String, Box<Value>),
    Map(BTreeMap<Value, Value>),
    Number(()),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

impl<'de> Deserialize<'de> for Value {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        deserializer.deserialize_any(ValueVisitor)
    }
}

struct ValueVisitor;

impl<'de> Visitor<'de> for ValueVisitor {
    type Value = Value;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "A RON value")
    }

    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Bool(v))
    }

    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
        where E: Error,
    {
        self.visit_f64(v as f64)
    }

    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_f64(v as f64)
    }

    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Number(( /*TODO*/ )))
    }

    fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Char(v))
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_string(v.to_owned())
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::String(v))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_byte_buf(v.to_vec())
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_string(String::from_utf8(v)
            .map_err(|e| Error::custom(format!("{}", e)))?)
    }

    fn visit_none<E>(self) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Option(None))
    }

    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
        where D: Deserializer<'de>,
    {
        Ok(Value::Option(Some(Box::new(deserializer.deserialize_any(ValueVisitor)?))))
    }

    fn visit_unit<E>(self) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Unit)
    }

    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
        where D: Deserializer<'de>
    {
        deserializer.deserialize_any(ValueVisitor)
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>
    {
        let mut vec = Vec::new();
        if let Some(cap) = seq.size_hint() {
            vec.reserve_exact(cap);
        }

        while let Some(x) = seq.next_element()? {
            vec.push(x);
        }

        Ok(Value::Seq(vec))
    }

    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
        where A: MapAccess<'de>
    {
        let mut res: BTreeMap<Value, Value> = BTreeMap::new();

        while let Some(entry) = map.next_entry()? {
            res.insert(entry.0, entry.1);
        }

        Ok(Value::Map(res))
    }

    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
        where A: EnumAccess<'de>
    {
        let (value, variant) = data.variant()?;

        Ok(Value::Enum(variant, Box::new(value)))
    }
}
<commit_msg>Remove visit_enum<commit_after>use std::collections::BTreeMap;
use std::fmt;

use serde::de::{Error, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer};

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Map(BTreeMap<Value, Value>),
    Number(()),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

impl<'de> Deserialize<'de> for Value {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        deserializer.deserialize_any(ValueVisitor)
    }
}

struct ValueVisitor;

impl<'de> Visitor<'de> for ValueVisitor {
    type Value = Value;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "A RON value")
    }

    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Bool(v))
    }

    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
        where E: Error,
    {
        self.visit_f64(v as f64)
    }

    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_f64(v as f64)
    }

    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Number(( /*TODO*/ )))
    }

    fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Char(v))
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_string(v.to_owned())
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::String(v))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_byte_buf(v.to_vec())
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
        where E: Error
    {
        self.visit_string(String::from_utf8(v)
            .map_err(|e| Error::custom(format!("{}", e)))?)
    }

    fn visit_none<E>(self) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Option(None))
    }

    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
        where D: Deserializer<'de>,
    {
        Ok(Value::Option(Some(Box::new(deserializer.deserialize_any(ValueVisitor)?))))
    }

    fn visit_unit<E>(self) -> Result<Self::Value, E>
        where E: Error
    {
        Ok(Value::Unit)
    }

    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
        where D: Deserializer<'de>
    {
        deserializer.deserialize_any(ValueVisitor)
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>
    {
        let mut vec = Vec::new();
        if let Some(cap) = seq.size_hint() {
            vec.reserve_exact(cap);
        }

        while let Some(x) = seq.next_element()? {
            vec.push(x);
        }

        Ok(Value::Seq(vec))
    }

    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
        where A: MapAccess<'de>
    {
        let mut res: BTreeMap<Value, Value> = BTreeMap::new();

        while let Some(entry) = map.next_entry()? {
            res.insert(entry.0, entry.1);
        }

        Ok(Value::Map(res))
    }
}
<|endoftext|>


<commit_before>
use serialize::json;
use serialize::Decodable;

struct Endpoint<T> {
	pub desc: &'static str,
	params: T
}

impl<T: Decodable<json::Decoder, json::DecoderError>> Endpoint<T> {
	pub fn decode(from: &str) -> T {
		json::decode(from).unwrap()
	}

	pub fn new(desc: &'static str, params_body: &str) -> Endpoint<T> {
		Endpoint {
			desc: desc,
			params: Endpoint::decode(params_body)
		}
	}
}

#[test]
fn params_decode() {

	#[deriving(Decodable)]
	struct Params {
		user_id: String,
		user_type: Option<String>
	};

	let endpoint: Endpoint<Params> = Endpoint::new("Test endpoint", "{\"user_id\": \"test\"}");

	assert_eq!(endpoint.params.user_id.as_slice(), "test");
	assert!(
		match endpoint.params.user_type {
			Some(String) => false,
			Nothing => true
		}
	)

}<commit_msg>feat: more convenient interface for Endpoint<commit_after>
use serialize::json;
use serialize::Decodable;

struct Endpoint<T> {
	pub desc: &'static str,
	handler: |&params: T|:'static -> String
}

impl<T: Decodable<json::Decoder, json::DecoderError>> Endpoint<T> {
	pub fn decode(from: &str) -> T {
		json::decode(from).unwrap()
	}

	pub fn process(self, params_body: &str) -> String {
		let params = Endpoint::decode(params_body);
		let handler = self.handler;
		handler(params)
	}

	pub fn new(desc: &'static str, handler: |&params: T|:'static -> String) -> Endpoint<T> {
		Endpoint {
			desc: desc,
			handler: handler
		}
	}
}

#[test]
fn params_decode() {

	#[deriving(Decodable)]
	struct Params {
		user_id: String,
		user_type: Option<String>
	};

	let endpoint: Endpoint<Params> = Endpoint::new(
		"Test endpoint",
		|params: Params| -> String {
			assert_eq!(params.user_id.as_slice(), "test");
			assert!(
				match params.user_type {
					Some(String) => false,
					Nothing => true
				}
			)

			"Result".to_string()
		}
	);

	assert_eq!(endpoint.process("{\"user_id\": \"test\"}").as_slice(), "Result");

}<|endoftext|>


<commit_before>use std::fmt;
use std::convert::From;
use std::sync::mpsc::{sync_channel, SyncSender, Receiver};
use std::io::{self, Read};

use rustc_serialize::json::{self, DecoderError};
use url::Url;
use hyper;
use hyper::client::request::Request;
use hyper::method::Method::Get;
use time::{Timespec, get_time, Duration, SteadyTime};

use irc::parse::IrcMsg;

use utils::formatting::duration_to_string;
use command_mapper::{
    RustBotPlugin,
    CommandMapperDispatch,
    IrcBotConfigurator,
    Format,
    Token,
};

static UPCOMING_URL: &'static str = "http://anime.yshi.org/api/calendar/upcoming/100";

const CMD_UPCOMING: Token = Token(0);

#[derive(RustcDecodable, RustcEncodable, Clone)]
struct Upcoming {
    title_name: String,
    syoboi_pid: i32,
    start_time: i64,
    end_time: i64,
    count: String,
    start_offset: i64,
    episode_name: String,
    channel_name: String,
    special_name: String,
    comment: String,
}

impl Upcoming {
    pub fn start_time(&self) -> Timespec {
        Timespec::new(self.start_time, 0)
    }

    pub fn end_time(&self) -> Timespec {
        Timespec::new(self.end_time, 0)
    }

    pub fn start_offset(&self) -> Duration {
        Duration::seconds(self.start_offset)
    }
}

impl fmt::Display for Upcoming {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let air_time_relative = self.start_time() - get_time();

        write!(f, "{} episode {} airs in {} on {}",
            self.title_name, self.count,
            duration_to_string(air_time_relative),
            self.channel_name)
    }
}

#[derive(Debug)]
enum ApiFailure {
    RequestError(hyper::Error),
    ResponseReadError(io::Error),
    ResponseDeserializeError(DecoderError)
}

impl From<hyper::Error> for ApiFailure {
    fn from(err: hyper::Error) -> ApiFailure {
        ApiFailure::RequestError(err)
    }
}

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

impl From<DecoderError> for ApiFailure {
    fn from(err: DecoderError) -> ApiFailure {
        ApiFailure::ResponseDeserializeError(err)
    }
}

fn get_upcoming() -> Result<Vec<Upcoming>, ApiFailure> {
    let url = Url::parse(UPCOMING_URL).ok().expect("Invalid UPCOMING_URL");
    let mut resp = try!(try!(try!(Request::new(Get, url)).start()).send());

    let mut body = String::new();
    try!(resp.read_to_string(&mut body));
    Ok(try!(json::decode::<Vec<Upcoming>>(&body)))
}

pub struct AnimeCalendarPlugin {
    sender: Option<SyncSender<(CommandMapperDispatch, IrcMsg)>>
}

impl AnimeCalendarPlugin {
    pub fn new() -> AnimeCalendarPlugin {
        AnimeCalendarPlugin { sender: None }
    }

    pub fn get_plugin_name() -> &'static str {
        "animecalendar"
    }
}

struct CacheItem<T, E> {
    retrieval_time: SteadyTime,
    value: Result<T, E>
}

struct Cache<T, E> {
    negative_expiry: Duration,
    positive_expiry: Duration,
    item: Option<CacheItem<T, E>>,
}

impl<T, E> Cache<T, E> {
    fn new() -> Cache<T, E> {
        Cache {
            negative_expiry: Duration::seconds(30),
            positive_expiry: Duration::minutes(5),
            item: None,
        }
    }

    fn is_valid(&self) -> bool {
        self.get().is_some()
    }

    fn set<'a>(&'a mut self, result: Result<T, E>) -> &'a Result<T, E> {
        self.item = Some(CacheItem {
            retrieval_time: SteadyTime::now(),
            value: result,
        });
        &self.item.as_ref().unwrap().value
    }

    fn get<'a>(&'a self) -> Option<&'a Result<T, E>> {
        let now = SteadyTime::now();
        match self.item {
            Some(ref item) => match item.value.is_ok() {
                true if now < item.retrieval_time + self.positive_expiry => {
                    Some(&item.value)
                },
                false if now < item.retrieval_time + self.negative_expiry => {
                    Some(&item.value)
                },
                _ => None
            },
            None => None,
        }
    }

    fn get_or_else<'a, F>(&'a mut self, func: F) -> &'a Result<T, E> where F: FnOnce() -> Result<T, E> {
        if self.is_valid() {
            self.get().unwrap()
        } else {
            let value = func();
            self.set(value)
        }
    }
}

struct AniCalInternal {
    cache: Cache<Vec<Upcoming>, ApiFailure>,
}

// This could be made allocation-free
fn lower_contains(haystack: &str, needle: &str) -> bool {
    let haystack = haystack.to_lowercase();
    let needle = needle.to_lowercase();

    haystack.contains(&needle)
}

fn maybe_lower_contains(haystack: &str, needle: Option<&str>) -> Option<bool> {
    needle.map(|n| lower_contains(haystack, n))
}

// THere must be a better way to do this.
fn maybe_str_ref<'a>(opt: &'a Option<String>) -> Option<&'a str> {
    match opt.as_ref() {
        Some(val) => Some(val.as_ref()),
        None => None
    }
}

impl AniCalInternal {
    fn new() -> AniCalInternal {
        AniCalInternal {
            cache: Cache::new(),
        }
    }

    fn handle_upcoming(&mut self, m: &CommandMapperDispatch, search: Option<&str>) {
        match *self.cache.get_or_else(get_upcoming) {
            Ok(ref records) => {
                let now = get_time();
                let found_records = records.iter()
                    .filter(|r| maybe_lower_contains(&r.title_name, search).unwrap_or(true))
                    .filter(|r| r.end_time() > now)
                    .take(5);

                let mut found = false;
                for record in found_records {
                    found = true;
                    m.reply(&format!("{}", record));
                }
                if !found {
                    m.reply("No results found");
                }
            }
            Err(ref err) => m.reply(&format!("err: {:?}", err)),
        }
    }

    fn start(&mut self, rx: Receiver<(CommandMapperDispatch, IrcMsg)>) {
        for (m, _) in rx.iter() {
            let command_phrase = m.command();
            match command_phrase.token {
                CMD_UPCOMING => {
                    let search = command_phrase.get::<String>(&"search");
                    self.handle_upcoming(&m, maybe_str_ref(&search))
                }
                _ => ()
            }
        }
    }
}

impl RustBotPlugin for AnimeCalendarPlugin {
    fn configure(&mut self, conf: &mut IrcBotConfigurator) {
        conf.map_format(CMD_UPCOMING, Format::from_str("upcoming").unwrap());
        conf.map_format(CMD_UPCOMING, Format::from_str("upcoming {*search}").unwrap());
        conf.map_format(CMD_UPCOMING, Format::from_str("showtime").unwrap());
        conf.map_format(CMD_UPCOMING, Format::from_str("showtime {*search}").unwrap());
    }

    fn start(&mut self) {
        info!("started AnimeCalendarPlugin");
        let (tx, rx) = sync_channel(10);
        self.sender = Some(tx);

        let _ = ::std::thread::Builder::new().name("plugin-animecalendar".to_string()).spawn(move || {
            info!("AniCalInternal started.");
            AniCalInternal::new().start(rx);
        });
    }

    fn dispatch_cmd(&mut self, m: &CommandMapperDispatch, message: &IrcMsg) {
        info!("dispatching AnimeCalendarPlugin command");
        match self.sender {
            Some(ref sender) => {
                if let Err(err) = sender.send((m.clone(), message.clone())) {
                    m.reply(&format!("Service ``animecalendar'' unavailable: {:?}", err));
                }
            }
            None => ()
        };
    }
}
<commit_msg>plugin(animecalendar): embolden response<commit_after>use std::fmt;
use std::convert::From;
use std::sync::mpsc::{sync_channel, SyncSender, Receiver};
use std::io::{self, Read};

use rustc_serialize::json::{self, DecoderError};
use url::Url;
use hyper;
use hyper::client::request::Request;
use hyper::method::Method::Get;
use time::{Timespec, get_time, Duration, SteadyTime};

use irc::parse::IrcMsg;

use utils::formatting::duration_to_string;
use command_mapper::{
    RustBotPlugin,
    CommandMapperDispatch,
    IrcBotConfigurator,
    Format,
    Token,
};

static UPCOMING_URL: &'static str = "http://anime.yshi.org/api/calendar/upcoming/100";

const CMD_UPCOMING: Token = Token(0);

#[derive(RustcDecodable, RustcEncodable, Clone)]
struct Upcoming {
    title_name: String,
    syoboi_pid: i32,
    start_time: i64,
    end_time: i64,
    count: String,
    start_offset: i64,
    episode_name: String,
    channel_name: String,
    special_name: String,
    comment: String,
}

impl Upcoming {
    pub fn start_time(&self) -> Timespec {
        Timespec::new(self.start_time, 0)
    }

    pub fn end_time(&self) -> Timespec {
        Timespec::new(self.end_time, 0)
    }

    pub fn start_offset(&self) -> Duration {
        Duration::seconds(self.start_offset)
    }
}

impl fmt::Display for Upcoming {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let air_time_relative = self.start_time() - get_time();

        write!(f, "\x02{}\x02 episode \x02{}\x02 airs in \x02{}\x02 on \x02{}\x02",
            self.title_name, self.count,
            duration_to_string(air_time_relative),
            self.channel_name)
    }
}

#[derive(Debug)]
enum ApiFailure {
    RequestError(hyper::Error),
    ResponseReadError(io::Error),
    ResponseDeserializeError(DecoderError)
}

impl From<hyper::Error> for ApiFailure {
    fn from(err: hyper::Error) -> ApiFailure {
        ApiFailure::RequestError(err)
    }
}

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

impl From<DecoderError> for ApiFailure {
    fn from(err: DecoderError) -> ApiFailure {
        ApiFailure::ResponseDeserializeError(err)
    }
}

fn get_upcoming() -> Result<Vec<Upcoming>, ApiFailure> {
    let url = Url::parse(UPCOMING_URL).ok().expect("Invalid UPCOMING_URL");
    let mut resp = try!(try!(try!(Request::new(Get, url)).start()).send());

    let mut body = String::new();
    try!(resp.read_to_string(&mut body));
    Ok(try!(json::decode::<Vec<Upcoming>>(&body)))
}

pub struct AnimeCalendarPlugin {
    sender: Option<SyncSender<(CommandMapperDispatch, IrcMsg)>>
}

impl AnimeCalendarPlugin {
    pub fn new() -> AnimeCalendarPlugin {
        AnimeCalendarPlugin { sender: None }
    }

    pub fn get_plugin_name() -> &'static str {
        "animecalendar"
    }
}

struct CacheItem<T, E> {
    retrieval_time: SteadyTime,
    value: Result<T, E>
}

struct Cache<T, E> {
    negative_expiry: Duration,
    positive_expiry: Duration,
    item: Option<CacheItem<T, E>>,
}

impl<T, E> Cache<T, E> {
    fn new() -> Cache<T, E> {
        Cache {
            negative_expiry: Duration::seconds(30),
            positive_expiry: Duration::minutes(5),
            item: None,
        }
    }

    fn is_valid(&self) -> bool {
        self.get().is_some()
    }

    fn set<'a>(&'a mut self, result: Result<T, E>) -> &'a Result<T, E> {
        self.item = Some(CacheItem {
            retrieval_time: SteadyTime::now(),
            value: result,
        });
        &self.item.as_ref().unwrap().value
    }

    fn get<'a>(&'a self) -> Option<&'a Result<T, E>> {
        let now = SteadyTime::now();
        match self.item {
            Some(ref item) => match item.value.is_ok() {
                true if now < item.retrieval_time + self.positive_expiry => {
                    Some(&item.value)
                },
                false if now < item.retrieval_time + self.negative_expiry => {
                    Some(&item.value)
                },
                _ => None
            },
            None => None,
        }
    }

    fn get_or_else<'a, F>(&'a mut self, func: F) -> &'a Result<T, E> where F: FnOnce() -> Result<T, E> {
        if self.is_valid() {
            self.get().unwrap()
        } else {
            let value = func();
            self.set(value)
        }
    }
}

struct AniCalInternal {
    cache: Cache<Vec<Upcoming>, ApiFailure>,
}

// This could be made allocation-free
fn lower_contains(haystack: &str, needle: &str) -> bool {
    let haystack = haystack.to_lowercase();
    let needle = needle.to_lowercase();

    haystack.contains(&needle)
}

fn maybe_lower_contains(haystack: &str, needle: Option<&str>) -> Option<bool> {
    needle.map(|n| lower_contains(haystack, n))
}

// THere must be a better way to do this.
fn maybe_str_ref<'a>(opt: &'a Option<String>) -> Option<&'a str> {
    match opt.as_ref() {
        Some(val) => Some(val.as_ref()),
        None => None
    }
}

impl AniCalInternal {
    fn new() -> AniCalInternal {
        AniCalInternal {
            cache: Cache::new(),
        }
    }

    fn handle_upcoming(&mut self, m: &CommandMapperDispatch, search: Option<&str>) {
        match *self.cache.get_or_else(get_upcoming) {
            Ok(ref records) => {
                let now = get_time();
                let found_records = records.iter()
                    .filter(|r| maybe_lower_contains(&r.title_name, search).unwrap_or(true))
                    .filter(|r| r.end_time() > now)
                    .take(5);

                let mut found = false;
                for record in found_records {
                    found = true;
                    m.reply(&format!("{}", record));
                }
                if !found {
                    m.reply("No results found");
                }
            }
            Err(ref err) => m.reply(&format!("err: {:?}", err)),
        }
    }

    fn start(&mut self, rx: Receiver<(CommandMapperDispatch, IrcMsg)>) {
        for (m, _) in rx.iter() {
            let command_phrase = m.command();
            match command_phrase.token {
                CMD_UPCOMING => {
                    let search = command_phrase.get::<String>(&"search");
                    self.handle_upcoming(&m, maybe_str_ref(&search))
                }
                _ => ()
            }
        }
    }
}

impl RustBotPlugin for AnimeCalendarPlugin {
    fn configure(&mut self, conf: &mut IrcBotConfigurator) {
        conf.map_format(CMD_UPCOMING, Format::from_str("upcoming").unwrap());
        conf.map_format(CMD_UPCOMING, Format::from_str("upcoming {*search}").unwrap());
        conf.map_format(CMD_UPCOMING, Format::from_str("showtime").unwrap());
        conf.map_format(CMD_UPCOMING, Format::from_str("showtime {*search}").unwrap());
    }

    fn start(&mut self) {
        info!("started AnimeCalendarPlugin");
        let (tx, rx) = sync_channel(10);
        self.sender = Some(tx);

        let _ = ::std::thread::Builder::new().name("plugin-animecalendar".to_string()).spawn(move || {
            info!("AniCalInternal started.");
            AniCalInternal::new().start(rx);
        });
    }

    fn dispatch_cmd(&mut self, m: &CommandMapperDispatch, message: &IrcMsg) {
        info!("dispatching AnimeCalendarPlugin command");
        match self.sender {
            Some(ref sender) => {
                if let Err(err) = sender.send((m.clone(), message.clone())) {
                    m.reply(&format!("Service ``animecalendar'' unavailable: {:?}", err));
                }
            }
            None => ()
        };
    }
}
<|endoftext|>


<commit_before>use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use humantime::parse_duration;
use std::time::Duration;
use time;

use super::error::*;
use failure::ResultExt;

#[derive(Default, Debug)]
pub struct CommandParser {
    on_date: Option<String>,
    at_time: Option<String>,
    in_duration: Option<String>,
    every_time: Option<String>,
    target: String,
    message: Option<String>,
}

#[derive(PartialEq, Clone, Copy)]
enum ParseState {
    None,
    On,
    At,
    In,
    Every,
    Msg,
}

impl CommandParser {
    pub fn parse_target(mut tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();

        if tokens.is_empty() {
            Err(ErrorKind::MissingReceiver)?;
        }

        parser.target = tokens.remove(0);

        parser.parse_tokens(tokens)
    }

    pub fn with_target(tokens: Vec<String>, target: String) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();
        parser.target = target;

        parser.parse_tokens(tokens)
    }

    fn parse_tokens(mut self, tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut state = ParseState::None;
        let mut cur_str = String::new();

        for token in tokens {
            let next_state = match token.as_ref() {
                "on" => ParseState::On,
                "at" => ParseState::At,
                "in" => ParseState::In,
                "every" => ParseState::Every,
                "to" => ParseState::Msg,
                _ => {
                    if !cur_str.is_empty() {
                        cur_str.push(' ');
                    }
                    cur_str.push_str(&token);
                    state
                }
            };

            if next_state != state {
                if state != ParseState::None {
                    self = self.add_string_by_state(state, cur_str)?;
                    cur_str = String::new();
                }

                state = next_state;
            }
        }

        self = self.add_string_by_state(state, cur_str)?;

        if self.message.is_none() {
            return Err(ErrorKind::MissingMessage.into());
        }

        if self.in_duration.is_some() && self.at_time.is_some()
            || self.in_duration.is_some() && self.on_date.is_some()
        {
            return Err(ErrorKind::AmbiguousTime.into());
        }

        if self.in_duration.is_none() && self.at_time.is_none() && self.on_date.is_none() {
            return Err(ErrorKind::MissingTime.into());
        }

        Ok(self)
    }

    fn add_string_by_state(self, state: ParseState, string: String) -> Result<Self, RemindError> {
        use self::ParseState::*;
        let string = Some(string);
        match state {
            On if self.on_date.is_none() => Ok(CommandParser {
                on_date: string,
                ..self
            }),
            At if self.at_time.is_none() => Ok(CommandParser {
                at_time: string,
                ..self
            }),
            In if self.in_duration.is_none() => Ok(CommandParser {
                in_duration: string,
                ..self
            }),
            Msg if self.message.is_none() => Ok(CommandParser {
                message: string,
                ..self
            }),
            Every if self.every_time.is_none() => Ok(CommandParser {
                every_time: string,
                ..self
            }),
            _ => Err(ErrorKind::MissingMessage.into()),
        }
    }

    fn parse_date(&self, str_date: &str) -> Result<NaiveDate, RemindError> {
        let nums = str_date
            .split('.')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidDate)?;

        if 2 > nums.len() || nums.len() > 3 {
            return Err(ErrorKind::InvalidDate.into());
        }

        let day = nums[0];
        let month = nums[1];

        let parse_date = match nums.get(2) {
            Some(year) => {
                NaiveDate::from_ymd_opt(*year as i32, month, day).ok_or(ErrorKind::InvalidDate)?
            }
            None => {
                let now = time::now();
                let date = NaiveDate::from_ymd_opt(now.tm_year + 1900, month, day)
                    .ok_or(ErrorKind::InvalidDate)?;
                if date.succ().and_hms(0, 0, 0).timestamp() < now.to_timespec().sec {
                    NaiveDate::from_ymd(now.tm_year + 1901, month, day)
                } else {
                    date
                }
            }
        };

        Ok(parse_date)
    }

    fn parse_time(&self, str_time: &str) -> Result<NaiveTime, RemindError> {
        let nums = str_time
            .split(':')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidTime)?;

        if 2 != nums.len() {
            return Err(ErrorKind::InvalidTime.into());
        }

        let hour = nums[0];
        let minute = nums[1];

        Ok(NaiveTime::from_hms(hour, minute, 0))
    }

    pub fn get_time(&self, min_dur: Duration) -> Result<NaiveDateTime, RemindError> {
        if let Some(ref str_duration) = self.in_duration {
            let duration = parse_duration(&str_duration).context(ErrorKind::InvalidTime)?;

            if duration < min_dur {
                return Err(ErrorKind::TimeShort.into());
            }

            let tm = time::now().to_timespec();
            return Ok(NaiveDateTime::from_timestamp(
                tm.sec + duration.as_secs() as i64,
                0u32,
            ));
        }

        let mut date = None;
        if let Some(ref str_date) = self.on_date {
            date = Some(self.parse_date(str_date)?);
        }

        if let Some(ref str_time) = self.at_time {
            let time = self.parse_time(str_time)?;

            if let Some(date) = date {
                Ok(date.and_time(time))
            } else {
                let now = time::now();
                let today = NaiveDate::from_ymd_opt(
                    now.tm_year + 1900,
                    now.tm_mon as u32 + 1,
                    now.tm_mday as u32,
                ).ok_or(ErrorKind::InvalidDate)?;

                let time_today = today.and_time(time);

                if time_today.timestamp() < now.to_timespec().sec {
                    debug!("tomorrow");

                    Ok(today.succ().and_time(time))
                } else {
                    debug!("today");

                    Ok(time_today)
                }
            }
        } else {
            Ok(date.expect("At this point date has to be set")
                .and_hms(0, 0, 0))
        }
    }

    pub fn get_repeat(&self, min_dur: Duration) -> Result<Option<Duration>, RemindError> {
        if let Some(mut words) = self.every_time.clone() {
            if !words.chars().next().unwrap().is_digit(10) {
                words.insert(0, '1');
            }
            let dur = parse_duration(&words).context(ErrorKind::InvalidTime)?;

            if dur <= min_dur {
                return Err(ErrorKind::RepeatTimeShort.into());
            }

            Ok(Some(dur))
        } else {
            Ok(None)
        }
    }

    pub fn get_target(&self) -> &str {
        &self.target
    }

    pub fn get_message(&self) -> &str {
        self.message.as_ref().expect("Has to be set")
    }
}
<commit_msg>Revert "Remind: Fix invalid error when parsing repeat time"<commit_after>use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use humantime::parse_duration;
use std::time::Duration;
use time;

use super::error::*;
use failure::ResultExt;

#[derive(Default, Debug)]
pub struct CommandParser {
    on_date: Option<String>,
    at_time: Option<String>,
    in_duration: Option<String>,
    every_time: Option<String>,
    target: String,
    message: Option<String>,
}

#[derive(PartialEq, Clone, Copy)]
enum ParseState {
    None,
    On,
    At,
    In,
    Every,
    Msg,
}

impl CommandParser {
    pub fn parse_target(mut tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();

        if tokens.is_empty() {
            Err(ErrorKind::MissingReceiver)?;
        }

        parser.target = tokens.remove(0);

        parser.parse_tokens(tokens)
    }

    pub fn with_target(tokens: Vec<String>, target: String) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();
        parser.target = target;

        parser.parse_tokens(tokens)
    }

    fn parse_tokens(mut self, tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut state = ParseState::None;
        let mut cur_str = String::new();

        for token in tokens {
            let next_state = match token.as_ref() {
                "on" => ParseState::On,
                "at" => ParseState::At,
                "in" => ParseState::In,
                "every" => ParseState::Every,
                "to" => ParseState::Msg,
                _ => {
                    if !cur_str.is_empty() {
                        cur_str.push(' ');
                    }
                    cur_str.push_str(&token);
                    state
                }
            };

            if next_state != state {
                if state != ParseState::None {
                    self = self.add_string_by_state(state, cur_str)?;
                    cur_str = String::new();
                }

                state = next_state;
            }
        }

        self = self.add_string_by_state(state, cur_str)?;

        if self.message.is_none() {
            return Err(ErrorKind::MissingMessage.into());
        }

        if self.in_duration.is_some() && self.at_time.is_some()
            || self.in_duration.is_some() && self.on_date.is_some()
        {
            return Err(ErrorKind::AmbiguousTime.into());
        }

        if self.in_duration.is_none() && self.at_time.is_none() && self.on_date.is_none() {
            return Err(ErrorKind::MissingTime.into());
        }

        Ok(self)
    }

    fn add_string_by_state(self, state: ParseState, string: String) -> Result<Self, RemindError> {
        use self::ParseState::*;
        let string = Some(string);
        match state {
            On if self.on_date.is_none() => Ok(CommandParser {
                on_date: string,
                ..self
            }),
            At if self.at_time.is_none() => Ok(CommandParser {
                at_time: string,
                ..self
            }),
            In if self.in_duration.is_none() => Ok(CommandParser {
                in_duration: string,
                ..self
            }),
            Msg if self.message.is_none() => Ok(CommandParser {
                message: string,
                ..self
            }),
            Every if self.every_time.is_none() => Ok(CommandParser {
                every_time: string,
                ..self
            }),
            _ => Err(ErrorKind::MissingMessage.into()),
        }
    }

    fn parse_date(&self, str_date: &str) -> Result<NaiveDate, RemindError> {
        let nums = str_date
            .split('.')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidDate)?;

        if 2 > nums.len() || nums.len() > 3 {
            return Err(ErrorKind::InvalidDate.into());
        }

        let day = nums[0];
        let month = nums[1];

        let parse_date = match nums.get(2) {
            Some(year) => {
                NaiveDate::from_ymd_opt(*year as i32, month, day).ok_or(ErrorKind::InvalidDate)?
            }
            None => {
                let now = time::now();
                let date = NaiveDate::from_ymd_opt(now.tm_year + 1900, month, day)
                    .ok_or(ErrorKind::InvalidDate)?;
                if date.succ().and_hms(0, 0, 0).timestamp() < now.to_timespec().sec {
                    NaiveDate::from_ymd(now.tm_year + 1901, month, day)
                } else {
                    date
                }
            }
        };

        Ok(parse_date)
    }

    fn parse_time(&self, str_time: &str) -> Result<NaiveTime, RemindError> {
        let nums = str_time
            .split(':')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidTime)?;

        if 2 != nums.len() {
            return Err(ErrorKind::InvalidTime.into());
        }

        let hour = nums[0];
        let minute = nums[1];

        Ok(NaiveTime::from_hms(hour, minute, 0))
    }

    pub fn get_time(&self, min_dur: Duration) -> Result<NaiveDateTime, RemindError> {
        if let Some(ref str_duration) = self.in_duration {
            let duration = parse_duration(&str_duration).context(ErrorKind::InvalidTime)?;

            if duration < min_dur {
                return Err(ErrorKind::TimeShort.into());
            }

            let tm = time::now().to_timespec();
            return Ok(NaiveDateTime::from_timestamp(
                tm.sec + duration.as_secs() as i64,
                0u32,
            ));
        }

        let mut date = None;
        if let Some(ref str_date) = self.on_date {
            date = Some(self.parse_date(str_date)?);
        }

        if let Some(ref str_time) = self.at_time {
            let time = self.parse_time(str_time)?;

            if let Some(date) = date {
                Ok(date.and_time(time))
            } else {
                let now = time::now();
                let today = NaiveDate::from_ymd_opt(
                    now.tm_year + 1900,
                    now.tm_mon as u32 + 1,
                    now.tm_mday as u32,
                ).ok_or(ErrorKind::InvalidDate)?;

                let time_today = today.and_time(time);

                if time_today.timestamp() < now.to_timespec().sec {
                    debug!("tomorrow");

                    Ok(today.succ().and_time(time))
                } else {
                    debug!("today");

                    Ok(time_today)
                }
            }
        } else {
            Ok(date.expect("At this point date has to be set")
                .and_hms(0, 0, 0))
        }
    }

    pub fn get_repeat(&self, min_dur: Duration) -> Result<Option<Duration>, RemindError> {
        if let Some(mut words) = self.every_time.clone() {
            if !words.chars().next().unwrap().is_digit(10) {
                words.insert(0, '1');
            }
            let dur = parse_duration(&words).context(ErrorKind::InvalidTime)?;

            if dur < min_dur {
                return Err(ErrorKind::RepeatTimeShort.into());
            }

            Ok(Some(dur))
        } else {
            Ok(None)
        }
    }

    pub fn get_target(&self) -> &str {
        &self.target
    }

    pub fn get_message(&self) -> &str {
        self.message.as_ref().expect("Has to be set")
    }
}
<|endoftext|>


<commit_before>//! A rustification of the `AudioStreamBasicDescription` type.
//!
//! Find the original `AudioStreamBasicDescription` reference [here](https://developer.apple.com/library/mac/documentation/MusicAudio/Reference/CoreAudioDataTypesRef/#//apple_ref/c/tdef/AudioStreamBasicDescription).

use bindings::audio_unit as au;
use error::{self, Error};
use super::audio_format::AudioFormat;

/// Representation of the AudioStreamBasicDescription.
#[derive(Copy, Clone, Debug)]
pub struct StreamFormat {
    pub sample_rate: f64,
    pub audio_format: AudioFormat,
    pub bytes_per_packet: u32,
    pub frames_per_packet: u32,
    pub bytes_per_frame: u32,
    pub channels_per_frame: u32,
    pub bits_per_channel: u32,
}

impl StreamFormat {

    /// Convert an AudioStreamBasicDescription into a StreamFormat.
    #[allow(non_snake_case)]
    pub fn from_asbd(asbd: au::AudioStreamBasicDescription) -> Result<StreamFormat, Error> {
        let au::Struct_AudioStreamBasicDescription {
            mSampleRate,
            mFormatID,
            mFormatFlags,
            mBytesPerPacket,
            mFramesPerPacket,
            mBytesPerFrame,
            mChannelsPerFrame,
            mBitsPerChannel,
            ..
        } = asbd;
        Ok(StreamFormat {
            sample_rate: mSampleRate,
            audio_format: match AudioFormat::from_format_and_flag(mFormatID, Some(mFormatFlags)) {
                Some(audio_format) => audio_format,
                None => return Err(Error::AudioUnit(error::audio_unit::Error::FormatNotSupported)),
            },
            bytes_per_packet: mBytesPerPacket,
            frames_per_packet: mFramesPerPacket,
            bytes_per_frame: mBytesPerFrame,
            channels_per_frame: mChannelsPerFrame,
            bits_per_channel: mBitsPerChannel,
        })
    }

    /// Convert a StreamFormat into an AudioStreamBasicDescription.
    pub fn to_asbd(self) -> au::AudioStreamBasicDescription {
        let StreamFormat {
            sample_rate,
            audio_format,
            bytes_per_packet,
            frames_per_packet,
            bytes_per_frame,
            channels_per_frame,
            bits_per_channel,
        } = self;
        let (format, maybe_flag) = audio_format.to_format_and_flag();
        let flag = maybe_flag.unwrap_or(::std::u32::MAX -2147483647);
        au::AudioStreamBasicDescription {
            mSampleRate: sample_rate,
            mFormatID: format,
            mFormatFlags: flag,
            mBytesPerPacket: bytes_per_packet,
            mFramesPerPacket: frames_per_packet,
            mBytesPerFrame: bytes_per_frame,
            mChannelsPerFrame: channels_per_frame,
            mBitsPerChannel: bits_per_channel,
            mReserved: 0,
        }
    }

    /// Return the number of channels.
    pub fn num_channels(&self) -> u32 {
        self.channels_per_frame
    }

}

<commit_msg>Remove unnecessary whitespace<commit_after>//! A rustification of the `AudioStreamBasicDescription` type.
//!
//! Find the original `AudioStreamBasicDescription` reference [here](https://developer.apple.com/library/mac/documentation/MusicAudio/Reference/CoreAudioDataTypesRef/#//apple_ref/c/tdef/AudioStreamBasicDescription).

use bindings::audio_unit as au;
use error::{self, Error};
use super::audio_format::AudioFormat;

/// Representation of the AudioStreamBasicDescription.
#[derive(Copy, Clone, Debug)]
pub struct StreamFormat {
    pub sample_rate: f64,
    pub audio_format: AudioFormat,
    pub bytes_per_packet: u32,
    pub frames_per_packet: u32,
    pub bytes_per_frame: u32,
    pub channels_per_frame: u32,
    pub bits_per_channel: u32,
}

impl StreamFormat {

    /// Convert an AudioStreamBasicDescription into a StreamFormat.
    #[allow(non_snake_case)]
    pub fn from_asbd(asbd: au::AudioStreamBasicDescription) -> Result<StreamFormat, Error> {
        let au::Struct_AudioStreamBasicDescription {
            mSampleRate,
            mFormatID,
            mFormatFlags,
            mBytesPerPacket,
            mFramesPerPacket,
            mBytesPerFrame,
            mChannelsPerFrame,
            mBitsPerChannel,
            ..
        } = asbd;
        Ok(StreamFormat {
            sample_rate: mSampleRate,
            audio_format: match AudioFormat::from_format_and_flag(mFormatID, Some(mFormatFlags)) {
                Some(audio_format) => audio_format,
                None => return Err(Error::AudioUnit(error::audio_unit::Error::FormatNotSupported)),
            },
            bytes_per_packet: mBytesPerPacket,
            frames_per_packet: mFramesPerPacket,
            bytes_per_frame: mBytesPerFrame,
            channels_per_frame: mChannelsPerFrame,
            bits_per_channel: mBitsPerChannel,
        })
    }

    /// Convert a StreamFormat into an AudioStreamBasicDescription.
    pub fn to_asbd(self) -> au::AudioStreamBasicDescription {
        let StreamFormat {
            sample_rate,
            audio_format,
            bytes_per_packet,
            frames_per_packet,
            bytes_per_frame,
            channels_per_frame,
            bits_per_channel,
        } = self;
        let (format, maybe_flag) = audio_format.to_format_and_flag();
        let flag = maybe_flag.unwrap_or(::std::u32::MAX -2147483647);
        au::AudioStreamBasicDescription {
            mSampleRate: sample_rate,
            mFormatID: format,
            mFormatFlags: flag,
            mBytesPerPacket: bytes_per_packet,
            mFramesPerPacket: frames_per_packet,
            mBytesPerFrame: bytes_per_frame,
            mChannelsPerFrame: channels_per_frame,
            mBitsPerChannel: bits_per_channel,
            mReserved: 0,
        }
    }

    /// Return the number of channels.
    pub fn num_channels(&self) -> u32 {
        self.channels_per_frame
    }

}
<|endoftext|>