<commit_before>//! Users

use std::borrow::Cow;

use types::{DateTime, WithheldScope};

/// Represents a user on Twitter.
///
/// # Reference
///
/// 1. [Users — Twitter Developers](https://dev.twitter.com/overview/api/users)
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct User<'a> {
    /// Indicates that the user has an account with “contributor mode” enabled,
    /// allowing for Tweets issued by the user to be co-authored
    /// by another account. Rarely `true`.
    pub contributors_enabled: bool,

    /// The UTC datetime that the user account was created on Twitter.
    #[serde(deserialize_with = "::util::deserialize_datetime")]
    pub created_at: DateTime,

    /// When `true`, indicates that the user has not altered
    /// the theme or background of their user profile.
    pub default_profile: bool,

    /// When `true`, indicates that the user has not uploaded their own avatar
    /// and a default egg avatar is used instead.
    pub default_profile_image: bool,

    /// The user-defined UTF-8 string describing their account.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub description: Option<Cow<'a, str>>,

    // pub entities: Entities, // does not appear in stream messages

    /// The number of tweets this user has favorited in the account’s lifetime.
    /// British spelling used in the field name for historical reasons.
    pub favourites_count: u64,

    /// *Perspectival*. When `true`, indicates that the authenticating user has
    /// issued a follow request to this protected user account.
    pub follow_request_sent: Option<bool>,

    // pub following: Option<bool>, // deprecated

    /// The number of followers this account currently has. Under certain
    /// conditions of duress, this field will temporarily indicate `0`.
    pub followers_count: u64,

    /// The number of users this account is following (AKA their “followings”).
    /// Under certain conditions of duress, this field will temporarily
    /// indicate `0`.
    pub friends_count: u64,

    /// When `true`, indicates that the user has enabled the possibility of
    /// geotagging their Tweets. This field must be `true` for the current user
    /// to attach geographic data when using [POST statuses / update][1].
    ///
    /// [1]: https://dev.twitter.com/rest/reference/post/statuses/update
    pub geo_enabled: bool,

    // does not appear in stream message
    // pub has_extended_profile: Option<bool>,

    /// The integer representation of the unique identifier for this User.
    pub id: UserId,

    // pub id_str: String,

    /// When `true`, indicates that the user is a participant in Twitter’s
    /// [translator community][1].
    ///
    /// [1]: http://translate.twttr.com/
    pub is_translator: bool,

    /// The [BCP 47][1] code for the user’s self-declared
    /// user interface language. May or may not have anything to do with
    /// the content of their Tweets.
    ///
    /// [1]: http://tools.ietf.org/html/bcp47
    #[serde(borrow)]
    pub lang: Cow<'a, str>,

    /// The number of public lists that this user is a member of.
    pub listed_count: u64,

    /// The user-defined location for this account’s profile.
    /// Not necessarily a location nor parseable. This field will occasionally
    /// be fuzzily interpreted by the Search service.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub location: Option<Cow<'a, str>>,

    /// The name of the user, as they’ve defined it. Not necessarily a person’s
    /// name. Typically capped at 20 characters, but subject to change.
    #[serde(borrow)]
    pub name: Cow<'a, str>,

    // pub notifications: Option<bool>, // deprecated

    /// The hexadecimal color chosen by the user for their background.
    #[serde(borrow)]
    pub profile_background_color: Cow<'a, str>,

    /// A HTTP-based URL pointing to the background image
    /// the user has uploaded for their profile.
    #[serde(borrow)]
    pub profile_background_image_url: Cow<'a, str>,

    /// A HTTPS-based URL pointing to the background image
    /// the user has uploaded for their profile.
    #[serde(borrow)]
    pub profile_background_image_url_https: Cow<'a, str>,

    /// When `true`, indicates that the user’s `profile_background_image_url`
    /// should be tiled when displayed.
    pub profile_background_tile: bool,

    /// The HTTPS-based URL pointing to the standard web representation of
    /// the user’s uploaded profile banner.
    /// By adding a final path element of the URL,
    /// you can obtain different image sizes optimized for specific displays.
    ///
    /// In the future, an API method will be provided to serve these URLs
    /// so that you need not modify the original URL.
    ///
    /// For size variations, please see [User Profile Images and Banners][1].
    ///
    /// [1]: https://dev.twitter.com/basics/user-profile-images-and-banners
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub profile_banner_url: Option<Cow<'a, str>>,

    /// A HTTP-based URL pointing to the user’s avatar image.
    /// See [User Profile Images and Banners][1].
    ///
    /// [1]: https://dev.twitter.com/basics/user-profile-images-and-banners
    #[serde(borrow)]
    pub profile_image_url: Cow<'a, str>,

    /// A HTTPS-based URL pointing to the user’s avatar image.
    #[serde(borrow)]
    pub profile_image_url_https: Cow<'a, str>,

    /// The hexadecimal color the user has chosen
    /// to display links with in their Twitter UI.
    #[serde(borrow)]
    pub profile_link_color: Cow<'a, str>,

    // pub profile_location: Option<_>, // does not appear in stream message

    /// The hexadecimal color the user has chosen
    /// to display sidebar borders with in their Twitter UI.
    #[serde(borrow)]
    pub profile_sidebar_border_color: Cow<'a, str>,

    /// The hexadecimal color the user has chosen
    /// to display sidebar backgrounds with in their Twitter UI.
    #[serde(borrow)]
    pub profile_sidebar_fill_color: Cow<'a, str>,

    /// The hexadecimal color the user has chosen
    /// to display text with in their Twitter UI.
    #[serde(borrow)]
    pub profile_text_color: Cow<'a, str>,

    /// When `true`, indicates the user wants their uploaded background image
    /// to be used.
    pub profile_use_background_image: bool,

    /// When `true`, indicates that this user has chosen to protect
    /// their Tweets. See [About Public and Protected Tweets][1].
    ///
    /// [1]: https://support.twitter.com/articles/14016-about-public-and-protected-tweets
    pub protected: bool,

    /// The screen name, handle, or alias that this user identifies themselves
    /// with.
    ///
    /// `screen_name`s are unique but subject to change.
    /// Use `id` as a user identifier whenever possible.
    ///
    /// Typically a maximum of 15 characters long,
    /// but some historical accounts may exist with longer names.
    #[serde(borrow)]
    pub screen_name: Cow<'a, str>,

    // pub show_all_inline_media: bool, // removed

    // pub status: Option<Box<Tweet>>, // does not appear in stream messages

    /// The number of tweets (including retweets) issued by the user.
    pub statuses_count: u64,

    /// A string describing the Time Zone this user declares themselves within.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub time_zone: Option<Cow<'a, str>>,

    /// A URL provided by the user in association with their profile.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub url: Option<Cow<'a, str>>,

    /// The offset from GMT/UTC in seconds.
    pub utc_offset: Option<i64>,

    /// When `true`, indicates that the user has a verified account.
    /// See [Verified Accounts][1].
    ///
    /// [1]: https://support.twitter.com/articles/119135-faqs-about-verified-accounts
    pub verified: bool,

    /// When present, indicates a textual representation of
    /// the two-letter country codes this user is withheld from.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub withheld_in_countries: Option<Cow<'a, str>>,

    /// When present, indicates whether the content being withheld is
    /// the `Status` or a `User`.
    #[serde(borrow)]
    pub withheld_scope: Option<WithheldScope<'a>>,
}

/// Numerical ID of a user.
pub type UserId = u64;
<commit_msg>profile_background_image* can be null<commit_after>//! Users

use std::borrow::Cow;

use types::{DateTime, WithheldScope};

/// Represents a user on Twitter.
///
/// # Reference
///
/// 1. [Users — Twitter Developers](https://dev.twitter.com/overview/api/users)
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct User<'a> {
    /// Indicates that the user has an account with “contributor mode” enabled,
    /// allowing for Tweets issued by the user to be co-authored
    /// by another account. Rarely `true`.
    pub contributors_enabled: bool,

    /// The UTC datetime that the user account was created on Twitter.
    #[serde(deserialize_with = "::util::deserialize_datetime")]
    pub created_at: DateTime,

    /// When `true`, indicates that the user has not altered
    /// the theme or background of their user profile.
    pub default_profile: bool,

    /// When `true`, indicates that the user has not uploaded their own avatar
    /// and a default egg avatar is used instead.
    pub default_profile_image: bool,

    /// The user-defined UTF-8 string describing their account.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub description: Option<Cow<'a, str>>,

    // pub entities: Entities, // does not appear in stream messages

    /// The number of tweets this user has favorited in the account’s lifetime.
    /// British spelling used in the field name for historical reasons.
    pub favourites_count: u64,

    /// *Perspectival*. When `true`, indicates that the authenticating user has
    /// issued a follow request to this protected user account.
    pub follow_request_sent: Option<bool>,

    // pub following: Option<bool>, // deprecated

    /// The number of followers this account currently has. Under certain
    /// conditions of duress, this field will temporarily indicate `0`.
    pub followers_count: u64,

    /// The number of users this account is following (AKA their “followings”).
    /// Under certain conditions of duress, this field will temporarily
    /// indicate `0`.
    pub friends_count: u64,

    /// When `true`, indicates that the user has enabled the possibility of
    /// geotagging their Tweets. This field must be `true` for the current user
    /// to attach geographic data when using [POST statuses / update][1].
    ///
    /// [1]: https://dev.twitter.com/rest/reference/post/statuses/update
    pub geo_enabled: bool,

    // does not appear in stream message
    // pub has_extended_profile: Option<bool>,

    /// The integer representation of the unique identifier for this User.
    pub id: UserId,

    // pub id_str: String,

    /// When `true`, indicates that the user is a participant in Twitter’s
    /// [translator community][1].
    ///
    /// [1]: http://translate.twttr.com/
    pub is_translator: bool,

    /// The [BCP 47][1] code for the user’s self-declared
    /// user interface language. May or may not have anything to do with
    /// the content of their Tweets.
    ///
    /// [1]: http://tools.ietf.org/html/bcp47
    #[serde(borrow)]
    pub lang: Cow<'a, str>,

    /// The number of public lists that this user is a member of.
    pub listed_count: u64,

    /// The user-defined location for this account’s profile.
    /// Not necessarily a location nor parseable. This field will occasionally
    /// be fuzzily interpreted by the Search service.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub location: Option<Cow<'a, str>>,

    /// The name of the user, as they’ve defined it. Not necessarily a person’s
    /// name. Typically capped at 20 characters, but subject to change.
    #[serde(borrow)]
    pub name: Cow<'a, str>,

    // pub notifications: Option<bool>, // deprecated

    /// The hexadecimal color chosen by the user for their background.
    #[serde(borrow)]
    pub profile_background_color: Cow<'a, str>,

    /// A HTTP-based URL pointing to the background image
    /// the user has uploaded for their profile.
    #[serde(borrow)]
    pub profile_background_image_url: Option<Cow<'a, str>>,

    /// A HTTPS-based URL pointing to the background image
    /// the user has uploaded for their profile.
    #[serde(borrow)]
    pub profile_background_image_url_https: Option<Cow<'a, str>>,

    /// When `true`, indicates that the user’s `profile_background_image_url`
    /// should be tiled when displayed.
    pub profile_background_tile: bool,

    /// The HTTPS-based URL pointing to the standard web representation of
    /// the user’s uploaded profile banner.
    /// By adding a final path element of the URL,
    /// you can obtain different image sizes optimized for specific displays.
    ///
    /// In the future, an API method will be provided to serve these URLs
    /// so that you need not modify the original URL.
    ///
    /// For size variations, please see [User Profile Images and Banners][1].
    ///
    /// [1]: https://dev.twitter.com/basics/user-profile-images-and-banners
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub profile_banner_url: Option<Cow<'a, str>>,

    /// A HTTP-based URL pointing to the user’s avatar image.
    /// See [User Profile Images and Banners][1].
    ///
    /// [1]: https://dev.twitter.com/basics/user-profile-images-and-banners
    #[serde(borrow)]
    pub profile_image_url: Cow<'a, str>,

    /// A HTTPS-based URL pointing to the user’s avatar image.
    #[serde(borrow)]
    pub profile_image_url_https: Cow<'a, str>,

    /// The hexadecimal color the user has chosen
    /// to display links with in their Twitter UI.
    #[serde(borrow)]
    pub profile_link_color: Cow<'a, str>,

    // pub profile_location: Option<_>, // does not appear in stream message

    /// The hexadecimal color the user has chosen
    /// to display sidebar borders with in their Twitter UI.
    #[serde(borrow)]
    pub profile_sidebar_border_color: Cow<'a, str>,

    /// The hexadecimal color the user has chosen
    /// to display sidebar backgrounds with in their Twitter UI.
    #[serde(borrow)]
    pub profile_sidebar_fill_color: Cow<'a, str>,

    /// The hexadecimal color the user has chosen
    /// to display text with in their Twitter UI.
    #[serde(borrow)]
    pub profile_text_color: Cow<'a, str>,

    /// When `true`, indicates the user wants their uploaded background image
    /// to be used.
    pub profile_use_background_image: bool,

    /// When `true`, indicates that this user has chosen to protect
    /// their Tweets. See [About Public and Protected Tweets][1].
    ///
    /// [1]: https://support.twitter.com/articles/14016-about-public-and-protected-tweets
    pub protected: bool,

    /// The screen name, handle, or alias that this user identifies themselves
    /// with.
    ///
    /// `screen_name`s are unique but subject to change.
    /// Use `id` as a user identifier whenever possible.
    ///
    /// Typically a maximum of 15 characters long,
    /// but some historical accounts may exist with longer names.
    #[serde(borrow)]
    pub screen_name: Cow<'a, str>,

    // pub show_all_inline_media: bool, // removed

    // pub status: Option<Box<Tweet>>, // does not appear in stream messages

    /// The number of tweets (including retweets) issued by the user.
    pub statuses_count: u64,

    /// A string describing the Time Zone this user declares themselves within.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub time_zone: Option<Cow<'a, str>>,

    /// A URL provided by the user in association with their profile.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub url: Option<Cow<'a, str>>,

    /// The offset from GMT/UTC in seconds.
    pub utc_offset: Option<i64>,

    /// When `true`, indicates that the user has a verified account.
    /// See [Verified Accounts][1].
    ///
    /// [1]: https://support.twitter.com/articles/119135-faqs-about-verified-accounts
    pub verified: bool,

    /// When present, indicates a textual representation of
    /// the two-letter country codes this user is withheld from.
    #[serde(borrow)]
    #[serde(default)]
    #[serde(deserialize_with = "::util::deserialize_opt_cow_str")]
    pub withheld_in_countries: Option<Cow<'a, str>>,

    /// When present, indicates whether the content being withheld is
    /// the `Status` or a `User`.
    #[serde(borrow)]
    pub withheld_scope: Option<WithheldScope<'a>>,
}

/// Numerical ID of a user.
pub type UserId = u64;
<|endoftext|>


<commit_before>extern crate x11;
extern crate libc;

use std::ptr;
use std::process::Command;
use std::boxed::Box;

use x11::xlib;
use super::WindowManager;
use super::Workspaces;
use super::container;
use super::layout::{self, LayoutDirection, MoveDirection};
use super::super::libx::{self, Context};

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyBind {
    pub key: xlib::KeySym,
    pub mask: u32,
}

impl KeyBind {
    pub fn build(mod_key: u32, tokens: &[&str]) -> KeyBind {
        let mut mask = 0;
        let mut sym = 0;
        for key in tokens {
            match *key {
                "$mod" => mask = mask | mod_key,
                "Shift" => mask = mask | xlib::ShiftMask,
                "Ctrl" => mask = mask | xlib::ControlMask,
                "Mod1" => mask = mask | xlib::Mod1Mask,
                "Mod2" => mask = mask | xlib::Mod2Mask,
                "Mod3" => mask = mask | xlib::Mod3Mask,
                "Mod4" => mask = mask | xlib::Mod4Mask,
                "Mod5" => mask = mask | xlib::Mod5Mask,
                _ => {
                    sym = libx::string_to_keysym(key);
                }
            }
        }

        KeyBind {
            mask: mask,
            key: sym
        }
    }
}

pub trait Handler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context);
}

pub struct ExecHandler {
    pub cmd: Command
}

pub struct LayoutHandler {
    layout_type: layout::Type,
}

pub struct FullscreenHandler;
/// switch to another workspace
pub struct WorkspaceHandler {
    pub key: char,
}

/// move window to target workspace
pub struct WindowToWorkspaceHandler {
    pub key: char,
}

pub struct WindowFocusHandler {
    pub direction: MoveDirection,
}

pub struct WindowCloseHandler;
pub struct SplitHandler;

pub enum Resize {
    Shrink,
    Grow,
}

pub struct WindowResizeHandler {
    pub direction: LayoutDirection,
    pub resize: Resize
}

impl Handler for WindowResizeHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let old = workspaces.mode;
        workspaces.mode = container::Mode::Layout;
        let mut changed = false;
        if let Some(c) = workspaces.get_focus() {
            if let Some(p) = c.get_parent() {
                let index = p.contain(c.raw_id()).unwrap();
                if p.direction == self.direction {
                    let step:f32 = match self.resize {
                        Resize::Shrink => {
                            -0.05
                        }
                        Resize::Grow => {
                            0.05
                        }
                    };

                    if index > 0 && index < (p.size() - 1) {
                        p.resize_children(index, index-1, step);
                        p.resize_children(index, index+1, step);
                    }
                    else if index > 0 {
                        p.resize_children(index, index-1, step*2.0);
                    }
                    else if index < (p.size() - 1) {
                        p.resize_children(index, index+1, step*2.0);
                    }
                    p.update_layout();
                    changed = true;
                }
            }
        }
        if !changed {
            workspaces.mode = old;
        }
    }
}

impl Handler for SplitHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        workspaces.current().print_tree(0);
        if let Some(c) = workspaces.get_focus() {
            c.split();
        }
        workspaces.current().print_tree(0);
    }
}

impl Handler for WindowCloseHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle window close");
        let (window, _) = libx::get_input_focus(context);
        libx::kill_window(context, window);
        // xlib::XWithdrawWindow(context, window, screen_num);
        // xlib::XDestroyWindow(context, window);
        println!("try kill window {}", window);

    }
}
impl Handler for WindowFocusHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("change focus in current workspace");
        if let Some(c) = workspaces.get_focus() {
            if let Some(p) = c.get_parent() {
                let index = p.contain(c.raw_id()).unwrap();
                let size = p.size();
                let next = match p.direction {
                    LayoutDirection::Vertical => {
                        match self.direction {
                            MoveDirection::Up => {
                                (index-1) % size
                            }
                            MoveDirection::Down => {
                                (index+1) % size
                            }
                            _ => { index }
                        }
                    }
                    LayoutDirection::Horizontal => {
                        match self.direction {
                            MoveDirection::Left => {
                                (index-1) % size
                            }
                            MoveDirection::Right => {
                                (index+1) % size
                            }
                            _ => { index }
                        }
                    }
                };
                if next != index {
                    c.unfocus();
                    let next_c = p.get_child(next).unwrap().focus();
                }
            }
        }
    }
}

impl Handler for WindowToWorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let id = match workspaces.get_focus() {
            Some(container) => {
                container.raw_id()
            }
            None => { return }
        };
        let from = workspaces.current_name();
        let to = self.key;
        workspaces.move_window(id, from, to);
    }
}

impl Handler for FullscreenHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("fullscreen toggle");
        if let Some(c) = workspaces.get_focus(){
            c.mode_toggle();
        }
    }
}
impl Handler for WorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle workspace form {}", workspaces.current_name());
        if !workspaces.contain(self.key) {
            workspaces.create(self.key);
        }
        workspaces.switch_workspace(self.key, context);
        println!("to {}", workspaces.current_name());
    }
}

impl Handler for ExecHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle exec");
        self.cmd.spawn();
    }
}

impl Handler for LayoutHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle layout");
        let t = self.layout_type.clone();
        let old = workspaces.mode;
        workspaces.mode = container::Mode::Layout;
        let mut changed = false;
        if let Some(container) = workspaces.get_focus() {
            let c = if container.get_parent().is_some() {
                container.get_parent().unwrap()
            }
            else {
                container
            };
            c.change_layout(t);
            c.update_layout();
            changed = true;
        }
        if !changed {
            workspaces.mode = old;
        }
    }
}

impl LayoutHandler {
    pub fn new(layout: layout::Type) -> LayoutHandler{
        LayoutHandler {
            layout_type: layout
        }
    }
}

impl ExecHandler {
    pub fn new(tokens: &[&str]) -> ExecHandler {
        let (name, args) = tokens.split_at(1);
        let mut cmd = Command::new(name[0]);
        cmd.args(args);

        let handler = ExecHandler {
            cmd: cmd,
        };
        handler
    }
}
<commit_msg>avoid negative u32<commit_after>extern crate x11;
extern crate libc;

use std::ptr;
use std::process::Command;
use std::boxed::Box;

use x11::xlib;
use super::WindowManager;
use super::Workspaces;
use super::container;
use super::layout::{self, LayoutDirection, MoveDirection};
use super::super::libx::{self, Context};

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyBind {
    pub key: xlib::KeySym,
    pub mask: u32,
}

impl KeyBind {
    pub fn build(mod_key: u32, tokens: &[&str]) -> KeyBind {
        let mut mask = 0;
        let mut sym = 0;
        for key in tokens {
            match *key {
                "$mod" => mask = mask | mod_key,
                "Shift" => mask = mask | xlib::ShiftMask,
                "Ctrl" => mask = mask | xlib::ControlMask,
                "Mod1" => mask = mask | xlib::Mod1Mask,
                "Mod2" => mask = mask | xlib::Mod2Mask,
                "Mod3" => mask = mask | xlib::Mod3Mask,
                "Mod4" => mask = mask | xlib::Mod4Mask,
                "Mod5" => mask = mask | xlib::Mod5Mask,
                _ => {
                    sym = libx::string_to_keysym(key);
                }
            }
        }

        KeyBind {
            mask: mask,
            key: sym
        }
    }
}

pub trait Handler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context);
}

pub struct ExecHandler {
    pub cmd: Command
}

pub struct LayoutHandler {
    layout_type: layout::Type,
}

pub struct FullscreenHandler;
/// switch to another workspace
pub struct WorkspaceHandler {
    pub key: char,
}

/// move window to target workspace
pub struct WindowToWorkspaceHandler {
    pub key: char,
}

pub struct WindowFocusHandler {
    pub direction: MoveDirection,
}

pub struct WindowCloseHandler;
pub struct SplitHandler;

pub enum Resize {
    Shrink,
    Grow,
}

pub struct WindowResizeHandler {
    pub direction: LayoutDirection,
    pub resize: Resize
}

impl Handler for WindowResizeHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let old = workspaces.mode;
        workspaces.mode = container::Mode::Layout;
        let mut changed = false;
        if let Some(c) = workspaces.get_focus() {
            if let Some(p) = c.get_parent() {
                let index = p.contain(c.raw_id()).unwrap();
                if p.direction == self.direction {
                    let step:f32 = match self.resize {
                        Resize::Shrink => {
                            -0.05
                        }
                        Resize::Grow => {
                            0.05
                        }
                    };

                    if index > 0 && index < (p.size() - 1) {
                        p.resize_children(index, index-1, step);
                        p.resize_children(index, index+1, step);
                    }
                    else if index > 0 {
                        p.resize_children(index, index-1, step*2.0);
                    }
                    else if index < (p.size() - 1) {
                        p.resize_children(index, index+1, step*2.0);
                    }
                    p.update_layout();
                    changed = true;
                }
            }
        }
        if !changed {
            workspaces.mode = old;
        }
    }
}

impl Handler for SplitHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        workspaces.current().print_tree(0);
        if let Some(c) = workspaces.get_focus() {
            c.split();
        }
        workspaces.current().print_tree(0);
    }
}

impl Handler for WindowCloseHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle window close");
        let (window, _) = libx::get_input_focus(context);
        libx::kill_window(context, window);
        // xlib::XWithdrawWindow(context, window, screen_num);
        // xlib::XDestroyWindow(context, window);
        println!("try kill window {}", window);

    }
}
impl Handler for WindowFocusHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("change focus in current workspace");
        if let Some(c) = workspaces.get_focus() {
            if let Some(p) = c.get_parent() {
                let index = p.contain(c.raw_id()).unwrap();
                let size = p.size();
                let next = match p.direction {
                    LayoutDirection::Vertical => {
                        match self.direction {
                            MoveDirection::Up => {
                                (index+size-1) % size
                            }
                            MoveDirection::Down => {
                                (index+1) % size
                            }
                            _ => { index }
                        }
                    }
                    LayoutDirection::Horizontal => {
                        match self.direction {
                            MoveDirection::Left => {
                                (index+size-1) % size
                            }
                            MoveDirection::Right => {
                                (index+1) % size
                            }
                            _ => { index }
                        }
                    }
                };
                if next != index {
                    c.unfocus();
                    let next_c = p.get_child(next).unwrap().focus();
                }
            }
        }
    }
}

impl Handler for WindowToWorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let id = match workspaces.get_focus() {
            Some(container) => {
                container.raw_id()
            }
            None => { return }
        };
        let from = workspaces.current_name();
        let to = self.key;
        workspaces.move_window(id, from, to);
    }
}

impl Handler for FullscreenHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("fullscreen toggle");
        if let Some(c) = workspaces.get_focus(){
            c.mode_toggle();
        }
    }
}
impl Handler for WorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle workspace form {}", workspaces.current_name());
        if !workspaces.contain(self.key) {
            workspaces.create(self.key);
        }
        workspaces.switch_workspace(self.key, context);
        println!("to {}", workspaces.current_name());
    }
}

impl Handler for ExecHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle exec");
        self.cmd.spawn();
    }
}

impl Handler for LayoutHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle layout");
        let t = self.layout_type.clone();
        let old = workspaces.mode;
        workspaces.mode = container::Mode::Layout;
        let mut changed = false;
        if let Some(container) = workspaces.get_focus() {
            let c = if container.get_parent().is_some() {
                container.get_parent().unwrap()
            }
            else {
                container
            };
            c.change_layout(t);
            c.update_layout();
            changed = true;
        }
        if !changed {
            workspaces.mode = old;
        }
    }
}

impl LayoutHandler {
    pub fn new(layout: layout::Type) -> LayoutHandler{
        LayoutHandler {
            layout_type: layout
        }
    }
}

impl ExecHandler {
    pub fn new(tokens: &[&str]) -> ExecHandler {
        let (name, args) = tokens.split_at(1);
        let mut cmd = Command::new(name[0]);
        cmd.args(args);

        let handler = ExecHandler {
            cmd: cmd,
        };
        handler
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! Low-level graphics abstraction for Rust. Mostly operates on data, not types.
//! Designed for use by libraries and higher-level abstractions only.

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
extern crate draw_state;
//extern crate num;

use std::fmt::Debug;
use std::hash::Hash;
use std::any::Any;

pub use draw_state::{state, target};
pub use self::factory::Factory;

pub mod buffer;
pub mod command;
pub mod dummy;
pub mod factory;
pub mod format;
pub mod handle;
pub mod mapping;
pub mod memory;
pub mod pso;
pub mod shade;
pub mod texture;

/// Compile-time maximum number of vertex attributes.
pub const MAX_VERTEX_ATTRIBUTES: usize = 16;
/// Compile-time maximum number of color targets.
pub const MAX_COLOR_TARGETS: usize = 4;
/// Compile-time maximum number of constant buffers.
pub const MAX_CONSTANT_BUFFERS: usize = 14;
/// Compile-time maximum number of shader resource views (SRV).
pub const MAX_RESOURCE_VIEWS: usize = 32;
/// Compile-time maximum number of unordered access views (UAV).
pub const MAX_UNORDERED_VIEWS: usize = 4;
/// Compile-time maximum number of samplers.
pub const MAX_SAMPLERS: usize = 16;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Number of vertices in a patch
pub type PatchSize = u8;

/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a constant buffer object.
pub type ConstantBufferSlot = u8;
/// Slot for a shader resource view.
pub type ResourceViewSlot = u8;
/// Slot for an unordered access object.
pub type UnorderedViewSlot = u8;
/// Slot for an active color buffer.
pub type ColorSlot = u8;
/// Slot for a sampler.
pub type SamplerSlot = u8;

macro_rules! define_shaders {
    ($($name:ident),+) => {$(
        #[allow(missing_docs)]
        #[derive(Clone, Debug, Eq, Hash, PartialEq)]
        pub struct $name<R: Resources>(handle::Shader<R>);
        impl<R: Resources> $name<R> {
            #[allow(missing_docs)]
            pub fn reference(&self, man: &mut handle::Manager<R>) -> &R::Shader {
                man.ref_shader(&self.0)
            }
        }
    )+}
}

define_shaders!(VertexShader, HullShader, DomainShader, GeometryShader, PixelShader);

/// A complete set of shaders to link a program.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ShaderSet<R: Resources> {
    /// Simple program: Vs-Ps
    Simple(VertexShader<R>, PixelShader<R>),
    /// Geometry shader programs: Vs-Gs-Ps
    Geometry(VertexShader<R>, GeometryShader<R>, PixelShader<R>),
    /// Tessellated TODO: Tessellated, TessellatedGeometry, TransformFeedback
    Tessellated(VertexShader<R>, HullShader<R>, DomainShader<R>, PixelShader<R>),

}

impl<R: Resources> ShaderSet<R> {
    /// Return the aggregated stage usage for the set.
    pub fn get_usage(&self) -> shade::Usage {
        match self {
            &ShaderSet::Simple(..) => shade::VERTEX | shade::PIXEL,
            &ShaderSet::Geometry(..) => shade::VERTEX | shade::GEOMETRY | shade::PIXEL,
            &ShaderSet::Tessellated(..) => shade::VERTEX | shade::HULL | shade::DOMAIN | shade::PIXEL,
        }
    }
}

//TODO: use the appropriate units for max vertex count, etc
/// Features that the device supports.
#[derive(Copy, Clone, Debug)]
#[allow(missing_docs)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub max_vertex_count: usize,
    pub max_index_count: usize,
    pub max_texture_size: usize,
    pub max_patch_size: usize,

    pub instance_base_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
    pub vertex_base_supported: bool,
    pub srgb_color_supported: bool,
    pub constant_buffer_supported: bool,
    pub unordered_access_view_supported: bool,
    pub separate_blending_slots_supported: bool,
}

/// Describes what geometric primitives are created from vertex data.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[repr(u8)]
pub enum Primitive {
    /// Each vertex represents a single point.
    PointList,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    LineList,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// Each quadtruplet of vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d]`, `b` and `c` form a line, and `a` and `d` are the adjacent
    /// vertices.
    LineListAdjacency,
    /// Every four consecutive vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d, e]`, `[a, b, c, d]` form a line segment with adjacency, and
    /// `[b, c, d, e]` form a line segment with adjacency.
    LineStripAdjacency,
    /// Each sextuplet of vertices represent a single traingle with adjacency information. For
    /// example, with `[a, b, c, d, e, f]`, `a`, `c`, and `e` form a traingle, and `b`, `d`, and
    /// `f` are the adjacent vertices, where `b` is adjacent to the edge formed by `a` and `c`, `d`
    /// is adjacent to the edge `c` and `e`, and `f` is adjacent to the edge `e` and `a`.
    TriangleListAdjacency,
    /// Every even-numbered vertex (every other starting from the first) represents an additional
    /// vertex for the triangle strip, while odd-numbered vertices (every other starting from the
    /// second) represent adjacent vertices. For example, with `[a, b, c, d, e, f, g, h]`, `[a, c,
    /// e, g]` form a triangle strip, and `[b, d, f, h]` are the adjacent vertices, where `b`, `d`,
    /// and `f` are adjacent to the first triangle in the strip, and `d`, `f`, and `h` are adjacent
    /// to the second.
    TriangleStripAdjacency,
    /// Patch list,
    /// used with shaders capable of producing primitives on their own (tessellation)
    PatchList(PatchSize),
}

/// A type of each index value in the slice's index buffer
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
#[repr(u8)]
pub enum IndexType {
    U16,
    U32,
}

/// Different types of a specific API.
#[allow(missing_docs)]
pub trait Resources:          Clone + Hash + Debug + Eq + PartialEq + Any {
    type Buffer:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Shader:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Program:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type PipelineStateObject: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Texture:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type ShaderResourceView:  Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type UnorderedAccessView: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type RenderTargetView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type DepthStencilView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Sampler:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Fence:               Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Mapping:             Hash + Debug + Eq + PartialEq + Any + Send + Sync + mapping::Gate<Self>;
}

/// A `Device` is responsible for submitting `CommandBuffer`s to the GPU.
pub trait Device: Sized {
    /// Associated `Resources` type.
    type Resources: Resources;
    /// Associated `CommandBuffer` type. Every `Device` type can only work with one `CommandBuffer`
    /// type.
    type CommandBuffer: command::Buffer<Self::Resources>;

    /// Returns the capabilities of this `Ðevice`.
    fn get_capabilities(&self) -> &Capabilities;

    /// Pin everything from this handle manager to live for a frame.
    fn pin_submitted_resources(&mut self, &handle::Manager<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.

    fn submit(&mut self, &mut Self::CommandBuffer,
                         access: &command::AccessInfo<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.
    /// returns a fence that is signaled after the GPU has executed all commands
    fn fenced_submit(&mut self,
                     &mut Self::CommandBuffer,
                     access: &command::AccessInfo<Self::Resources>,
                     after: Option<handle::Fence<Self::Resources>>)
                     -> handle::Fence<Self::Resources>;

    /// Stalls the current thread until the fence is satisfied
    fn wait_fence(&mut self, &handle::Fence<Self::Resources>);

    /// Cleanup unused resources. This should be called between frames.
    fn cleanup(&mut self);
}
<commit_msg>Auto merge of #1162 - msiglreith:core_merge, r=kvark<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! Low-level graphics abstraction for Rust. Mostly operates on data, not types.
//! Designed for use by libraries and higher-level abstractions only.

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
extern crate draw_state;
//extern crate num;

use std::fmt::Debug;
use std::hash::Hash;
use std::any::Any;

pub use draw_state::{state, target};
pub use self::factory::Factory;

pub mod buffer;
pub mod command;
pub mod dummy;
pub mod factory;
pub mod format;
pub mod handle;
pub mod mapping;
pub mod memory;
pub mod pso;
pub mod shade;
pub mod texture;

/// Compile-time maximum number of vertex attributes.
pub const MAX_VERTEX_ATTRIBUTES: usize = 16;
/// Compile-time maximum number of color targets.
pub const MAX_COLOR_TARGETS: usize = 4;
/// Compile-time maximum number of constant buffers.
pub const MAX_CONSTANT_BUFFERS: usize = 14;
/// Compile-time maximum number of shader resource views (SRV).
pub const MAX_RESOURCE_VIEWS: usize = 32;
/// Compile-time maximum number of unordered access views (UAV).
pub const MAX_UNORDERED_VIEWS: usize = 4;
/// Compile-time maximum number of samplers.
pub const MAX_SAMPLERS: usize = 16;

/// Draw vertex count.
pub type VertexCount = u32;
/// Draw number of instances
pub type InstanceCount = u32;
/// Number of vertices in a patch
pub type PatchSize = u8;

/// Slot for an attribute.
pub type AttributeSlot = u8;
/// Slot for a constant buffer object.
pub type ConstantBufferSlot = u8;
/// Slot for a shader resource view.
pub type ResourceViewSlot = u8;
/// Slot for an unordered access object.
pub type UnorderedViewSlot = u8;
/// Slot for an active color buffer.
pub type ColorSlot = u8;
/// Slot for a sampler.
pub type SamplerSlot = u8;

macro_rules! define_shaders {
    ($($name:ident),+) => {$(
        #[allow(missing_docs)]
        #[derive(Clone, Debug, Eq, Hash, PartialEq)]
        pub struct $name<R: Resources>(handle::Shader<R>);
        impl<R: Resources> $name<R> {
            #[allow(missing_docs)]
            pub fn reference(&self, man: &mut handle::Manager<R>) -> &R::Shader {
                man.ref_shader(&self.0)
            }
        }
    )+}
}

define_shaders!(VertexShader, HullShader, DomainShader, GeometryShader, PixelShader);

/// A complete set of shaders to link a program.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ShaderSet<R: Resources> {
    /// Simple program: Vs-Ps
    Simple(VertexShader<R>, PixelShader<R>),
    /// Geometry shader programs: Vs-Gs-Ps
    Geometry(VertexShader<R>, GeometryShader<R>, PixelShader<R>),
    /// Tessellated TODO: Tessellated, TessellatedGeometry, TransformFeedback
    Tessellated(VertexShader<R>, HullShader<R>, DomainShader<R>, PixelShader<R>),

}

impl<R: Resources> ShaderSet<R> {
    /// Return the aggregated stage usage for the set.
    pub fn get_usage(&self) -> shade::Usage {
        match self {
            &ShaderSet::Simple(..) => shade::VERTEX | shade::PIXEL,
            &ShaderSet::Geometry(..) => shade::VERTEX | shade::GEOMETRY | shade::PIXEL,
            &ShaderSet::Tessellated(..) => shade::VERTEX | shade::HULL | shade::DOMAIN | shade::PIXEL,
        }
    }
}

//TODO: use the appropriate units for max vertex count, etc
/// Features that the device supports.
#[derive(Copy, Clone, Debug)]
#[allow(missing_docs)] // pretty self-explanatory fields!
pub struct Capabilities {
    pub max_vertex_count: usize,
    pub max_index_count: usize,
    pub max_texture_size: usize,
    pub max_patch_size: usize,

    pub instance_base_supported: bool,
    pub instance_call_supported: bool,
    pub instance_rate_supported: bool,
    pub vertex_base_supported: bool,
    pub srgb_color_supported: bool,
    pub constant_buffer_supported: bool,
    pub unordered_access_view_supported: bool,
    pub separate_blending_slots_supported: bool,
}

/// Describes what geometric primitives are created from vertex data.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[repr(u8)]
pub enum Primitive {
    /// Each vertex represents a single point.
    PointList,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    LineList,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// Each quadtruplet of vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d]`, `b` and `c` form a line, and `a` and `d` are the adjacent
    /// vertices.
    LineListAdjacency,
    /// Every four consecutive vertices represent a single line segment with adjacency information.
    /// For example, with `[a, b, c, d, e]`, `[a, b, c, d]` form a line segment with adjacency, and
    /// `[b, c, d, e]` form a line segment with adjacency.
    LineStripAdjacency,
    /// Each sextuplet of vertices represent a single traingle with adjacency information. For
    /// example, with `[a, b, c, d, e, f]`, `a`, `c`, and `e` form a traingle, and `b`, `d`, and
    /// `f` are the adjacent vertices, where `b` is adjacent to the edge formed by `a` and `c`, `d`
    /// is adjacent to the edge `c` and `e`, and `f` is adjacent to the edge `e` and `a`.
    TriangleListAdjacency,
    /// Every even-numbered vertex (every other starting from the first) represents an additional
    /// vertex for the triangle strip, while odd-numbered vertices (every other starting from the
    /// second) represent adjacent vertices. For example, with `[a, b, c, d, e, f, g, h]`, `[a, c,
    /// e, g]` form a triangle strip, and `[b, d, f, h]` are the adjacent vertices, where `b`, `d`,
    /// and `f` are adjacent to the first triangle in the strip, and `d`, `f`, and `h` are adjacent
    /// to the second.
    TriangleStripAdjacency,
    /// Patch list,
    /// used with shaders capable of producing primitives on their own (tessellation)
    PatchList(PatchSize),
}

/// A type of each index value in the slice's index buffer
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
#[repr(u8)]
pub enum IndexType {
    U16,
    U32,
}

/// Different types of a specific API.
#[allow(missing_docs)]
pub trait Resources:          Clone + Hash + Debug + Eq + PartialEq + Any {
    type Buffer:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Shader:              Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Program:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type PipelineStateObject: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Texture:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type ShaderResourceView:  Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type UnorderedAccessView: Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type RenderTargetView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type DepthStencilView:    Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Sampler:             Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync + Copy;
    type Fence:               Clone + Hash + Debug + Eq + PartialEq + Any + Send + Sync;
    type Mapping:             Hash + Debug + Eq + PartialEq + Any + Send + Sync + mapping::Gate<Self>;
}

/// A `Device` is responsible for submitting `CommandBuffer`s to the GPU.
pub trait Device: Sized {
    /// Associated `Resources` type.
    type Resources: Resources;
    /// Associated `CommandBuffer` type. Every `Device` type can only work with one `CommandBuffer`
    /// type.
    type CommandBuffer: command::Buffer<Self::Resources>;

    /// Returns the capabilities of this `Ðevice`.
    fn get_capabilities(&self) -> &Capabilities;

    /// Pin everything from this handle manager to live for a frame.
    fn pin_submitted_resources(&mut self, &handle::Manager<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.

    fn submit(&mut self, &mut Self::CommandBuffer,
                         access: &command::AccessInfo<Self::Resources>);

    /// Submits a `CommandBuffer` to the GPU for execution.
    /// returns a fence that is signaled after the GPU has executed all commands
    fn fenced_submit(&mut self,
                     &mut Self::CommandBuffer,
                     access: &command::AccessInfo<Self::Resources>,
                     after: Option<handle::Fence<Self::Resources>>)
                     -> handle::Fence<Self::Resources>;

    /// Stalls the current thread until the fence is satisfied
    fn wait_fence(&mut self, &handle::Fence<Self::Resources>);

    /// Cleanup unused resources. This should be called between frames.
    fn cleanup(&mut self);
}

/// Represents a physical or virtual device, which is capable of running the backend.
pub trait Adapter: Sized {
    /// Associated `CommandQueue` type.
    type CommandQueue: CommandQueue;
    /// Associated `Device` type.
    type Device: Device;
    /// Associated `QueueFamily` type.
    type QueueFamily: QueueFamily;

    /// Enumerate all available adapters supporting this backend
    fn enumerate_adapters() -> Vec<Self>;

    /// Create a new device and command queues.
    fn open<'a, I>(&self, queue_descs: I) -> (Self::Device, Vec<Self::CommandQueue>)
        where I: Iterator<Item=(&'a Self::QueueFamily, u32)>;

    /// Get the `AdapterInfo` for this adapater.
    fn get_info(&self) -> &AdapterInfo;

    /// Return the supported queue families for this adapter.
    fn get_queue_families(&self) -> &[Self::QueueFamily];
}

/// Information about a backend adapater.
#[derive(Clone, Debug)]
pub struct AdapterInfo {
    /// Adapter name
    pub name: String,
    /// Vendor PCI id of the adapter
    pub vendor: usize,
    /// PCI id of the adapter
    pub device: usize,
    /// The device is based on a software rasterizer
    pub software_rendering: bool,
}

/// `QueueFamily` denotes a group of command queues provided by the backend
/// with the same properties/type.
pub trait QueueFamily: 'static {
    /// Associated `Surface` type.
    type Surface: Surface;

    /// Check if the queue family supports presentation to a surface
    fn supports_present(&self, surface: &Self::Surface) -> bool;

    /// Return the number of available queues of this family
    // TODO: some backends like d3d12 support infinite software queues (verify)
    fn num_queues(&self) -> u32;
}

/// Dummy trait for command queues.
/// CommandBuffers will be later submitted to command queues instead of the device.
pub trait CommandQueue { }

/// A `Surface` abstracts the surface of a native window, which will be presented
pub trait Surface {
    /// Associated `CommandQueue` type.
    type CommandQueue: CommandQueue;
    /// Associated `SwapChain` type.
    type SwapChain: SwapChain;
    /// Associated native `Window` type.
    type Window;

    /// Create a new surface from a native window.
    fn from_window(window: &Self::Window) -> Self;

    /// Create a new swapchain from the current surface with an associated present queue.
    fn build_swapchain<T: format::RenderFormat>(&self, present_queue: &Self::CommandQueue)
        -> Self::SwapChain;
}

/// Handle to a backbuffer of the swapchain.
pub struct Frame(usize);

impl Frame {
    #[doc(hidden)]
    pub fn new(id: usize) -> Self {
        Frame(id)
    }
}

/// The `SwapChain` is the backend representation of the surface.
/// It consists of multiple buffers, which will be presented on the surface.
pub trait SwapChain {
    /// Acquire a new frame for rendering. This needs to be called before presenting.
    fn acquire_frame(&mut self) -> Frame;

    /// Present one acquired frame in FIFO order.
    fn present(&mut self);
}
<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
use proc_macro2;
use syn;
use syn::punctuated;
use syn::token;

use derives;
use derives::attrs::{Attrs, Kind, Parser, Ty};
use derives::from_argmatches;
use derives::into_app;

/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an app.
fn gen_app_augmentation(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    app_var: &syn::Ident,
) -> proc_macro2::TokenStream {
    let subcmds: Vec<_> = fields
        .iter()
        .filter_map(|field| {
            let attrs = Attrs::from_field(&field);
            if let Kind::Subcommand(ty) = attrs.kind() {
                let subcmd_type = match (ty, derives::sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let required = if ty == Ty::Option {
                    quote!()
                } else {
                    quote! {
                        let #app_var = #app_var.setting(
                            ::clap::AppSettings::SubcommandRequiredElseHelp
                        );
                    }
                };

                Some(quote! {
                    let #app_var = <#subcmd_type>::augment_app( #app_var );
                    #required
                })
            } else {
                None
            }
        })
        .collect();

    assert!(
        subcmds.len() <= 1,
        "cannot have more than one nested subcommand"
    );

    let args = fields.iter().filter_map(|field| {
        let attrs = Attrs::from_field(field);
        match attrs.kind() {
            Kind::Subcommand(_) => None,
            Kind::FlattenStruct => {
                let ty = &field.ty;
                Some(quote! {
                    let #app_var = <#ty>::augment_app(#app_var);
                    let #app_var = if <#ty>::is_subcommand() {
                        #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp)
                    } else {
                        #app_var
                    };
                })
            }
            Kind::Arg(ty) => {
                let convert_type = match ty {
                    Ty::Vec | Ty::Option => derives::sub_type(&field.ty).unwrap_or(&field.ty),
                    _ => &field.ty,
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;

                let validator = match *attrs.parser() {
                    (Parser::TryFromStr, ref f) => quote! {
                        .validator(|s| {
                            #f(&s)
                            .map(|_: #convert_type| ())
                            .map_err(|e| e.to_string())
                        })
                    },
                    (Parser::TryFromOsStr, ref f) => quote! {
                        .validator_os(|s| #f(&s).map(|_: #convert_type| ()))
                    },
                    _ => quote!(),
                };

                // @TODO remove unneccessary builders
                let modifier = match ty {
                    Ty::Bool => quote!(),
                    Ty::Option => quote!( .takes_value(true) #validator ),
                    Ty::Vec => quote!( .takes_value(true).multiple(true) #validator ),
                    Ty::Other if occurences => quote!( .multiple_occurrences(true) ),
                    Ty::Other => {
                        let required = !attrs.has_method("default_value");
                        quote!( .takes_value(true).required(#required) #validator )
                    }
                };
                let methods = attrs.methods();
                let name = attrs.name();
                Some(quote! {
                    let #app_var = #app_var.arg(
                        ::clap::Arg::with_name(#name)
                            #modifier
                            #methods
                    );
                })
            }
        }
    });

    quote! {{
        #( #args )*
        #( #subcmds )*
        #app_var
    }}
}

fn gen_augment_app_fn(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
) -> proc_macro2::TokenStream {
    let app_var = syn::Ident::new("app", proc_macro2::Span::call_site());
    let augmentation = gen_app_augmentation(fields, &app_var);
    quote! {
        pub fn augment_app<'b>(
            #app_var: ::clap::App<'b>
        ) -> ::clap::App<'b> {
            #augmentation
        }
    }
}

fn gen_augment_app_for_enum(
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let subcommands = variants.iter().map(|variant| {
        let name = variant.ident.to_string();
        let attrs = Attrs::from_struct(&variant.attrs, name);
        let app_var = syn::Ident::new("subcommand", proc_macro2::Span::call_site());
        let arg_block = match variant.fields {
            Named(ref fields) => gen_app_augmentation(&fields.named, &app_var),
            Unit => quote!( #app_var ),
            Unnamed(syn::FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                let ty = &unnamed[0];
                quote! {
                    {
                        let #app_var = <#ty>::augment_app(#app_var);
                        if <#ty>::is_subcommand() {
                            #app_var.setting(
                                ::clap::AppSettings::SubcommandRequiredElseHelp
                            )
                        } else {
                            #app_var
                        }
                    }
                }
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        let name = attrs.name();
        let from_attrs = attrs.methods();
        quote! {
            .subcommand({
                let #app_var = ::clap::App::new(#name);
                let #app_var = #arg_block;
                #app_var#from_attrs
            })
        }
    });

    quote! {
        pub fn augment_app<'b>(
            app: ::clap::App<'b>
        ) -> ::clap::App<'b> {
            app #( #subcommands )*
        }
    }
}

fn gen_from_subcommand(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let match_arms = variants.iter().map(|variant| {
        let attrs = Attrs::from_struct(&variant.attrs, variant.ident.to_string());
        let sub_name = attrs.name();
        let variant_name = &variant.ident;
        let constructor_block = match variant.fields {
            Named(ref fields) => from_argmatches::gen_constructor(&fields.named),
            Unit => quote!(),
            Unnamed(ref fields) if fields.unnamed.len() == 1 => {
                let ty = &fields.unnamed[0];
                quote!( ( <#ty as ::clap::FromArgMatches>::from_argmatches(matches) ) )
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        quote! {
            (#sub_name, Some(matches)) =>
                Some(#name :: #variant_name #constructor_block)
        }
    });

    quote! {
        pub fn from_subcommand<'b>(
            sub: (&'b str, Option<&'b ::clap::ArgMatches>)
        ) -> Option<Self> {
            match sub {
                #( #match_arms ),*,
                _ => None
            }
        }
    }
}

fn clap_impl_for_struct(
    name: &syn::Ident,
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_struct(name, attrs);
    let augment_app_fn = gen_augment_app_fn(fields);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_struct(name, fields);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #parse_fns

            pub fn is_subcommand() -> bool { false }
        }
    }
}

fn clap_impl_for_enum(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_enum(name, attrs);
    let augment_app_fn = gen_augment_app_for_enum(variants);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_enum(name);
    let from_subcommand = gen_from_subcommand(name, variants);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(unused_variables, dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #from_subcommand

            #parse_fns

            pub fn is_subcommand() -> bool { true }
        }
    }
}

pub fn derive_clap(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
    use syn::Data::*;

    let struct_name = &input.ident;
    let inner_impl = match input.data {
        Struct(syn::DataStruct {
            fields: syn::Fields::Named(ref fields),
            ..
        }) => clap_impl_for_struct(struct_name, &fields.named, &input.attrs),
        Enum(ref e) => clap_impl_for_enum(struct_name, &e.variants, &input.attrs),
        _ => panic!("clap_derive only supports non-tuple structs and enums"),
    };

    quote!(#inner_impl)
}

fn gen_parse_fns(name: &syn::Ident) -> proc_macro2::TokenStream {
    quote! {
        fn parse() -> #name {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches())
        }

        fn try_parse() -> ::std::result::Result<#name, ::clap::Error> {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().try_get_matches()?))
        }

        fn parse_from<I, T>(itr: I) -> #name
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches_from(itr))
        }

        fn try_parse_from<I, T>(itr: I) -> ::std::result::Result<#name, ::clap::Error>
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().try_get_matches_from(itr)?))
        }
    }
}
<commit_msg>Adding pub to the parse functions<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
use proc_macro2;
use syn;
use syn::punctuated;
use syn::token;

use derives;
use derives::attrs::{Attrs, Kind, Parser, Ty};
use derives::from_argmatches;
use derives::into_app;

/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an app.
fn gen_app_augmentation(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    app_var: &syn::Ident,
) -> proc_macro2::TokenStream {
    let subcmds: Vec<_> = fields
        .iter()
        .filter_map(|field| {
            let attrs = Attrs::from_field(&field);
            if let Kind::Subcommand(ty) = attrs.kind() {
                let subcmd_type = match (ty, derives::sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let required = if ty == Ty::Option {
                    quote!()
                } else {
                    quote! {
                        let #app_var = #app_var.setting(
                            ::clap::AppSettings::SubcommandRequiredElseHelp
                        );
                    }
                };

                Some(quote! {
                    let #app_var = <#subcmd_type>::augment_app( #app_var );
                    #required
                })
            } else {
                None
            }
        })
        .collect();

    assert!(
        subcmds.len() <= 1,
        "cannot have more than one nested subcommand"
    );

    let args = fields.iter().filter_map(|field| {
        let attrs = Attrs::from_field(field);
        match attrs.kind() {
            Kind::Subcommand(_) => None,
            Kind::FlattenStruct => {
                let ty = &field.ty;
                Some(quote! {
                    let #app_var = <#ty>::augment_app(#app_var);
                    let #app_var = if <#ty>::is_subcommand() {
                        #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp)
                    } else {
                        #app_var
                    };
                })
            }
            Kind::Arg(ty) => {
                let convert_type = match ty {
                    Ty::Vec | Ty::Option => derives::sub_type(&field.ty).unwrap_or(&field.ty),
                    _ => &field.ty,
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;

                let validator = match *attrs.parser() {
                    (Parser::TryFromStr, ref f) => quote! {
                        .validator(|s| {
                            #f(&s)
                            .map(|_: #convert_type| ())
                            .map_err(|e| e.to_string())
                        })
                    },
                    (Parser::TryFromOsStr, ref f) => quote! {
                        .validator_os(|s| #f(&s).map(|_: #convert_type| ()))
                    },
                    _ => quote!(),
                };

                // @TODO remove unneccessary builders
                let modifier = match ty {
                    Ty::Bool => quote!(),
                    Ty::Option => quote!( .takes_value(true) #validator ),
                    Ty::Vec => quote!( .takes_value(true).multiple(true) #validator ),
                    Ty::Other if occurences => quote!( .multiple_occurrences(true) ),
                    Ty::Other => {
                        let required = !attrs.has_method("default_value");
                        quote!( .takes_value(true).required(#required) #validator )
                    }
                };
                let methods = attrs.methods();
                let name = attrs.name();
                Some(quote! {
                    let #app_var = #app_var.arg(
                        ::clap::Arg::with_name(#name)
                            #modifier
                            #methods
                    );
                })
            }
        }
    });

    quote! {{
        #( #args )*
        #( #subcmds )*
        #app_var
    }}
}

fn gen_augment_app_fn(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
) -> proc_macro2::TokenStream {
    let app_var = syn::Ident::new("app", proc_macro2::Span::call_site());
    let augmentation = gen_app_augmentation(fields, &app_var);
    quote! {
        pub fn augment_app<'b>(
            #app_var: ::clap::App<'b>
        ) -> ::clap::App<'b> {
            #augmentation
        }
    }
}

fn gen_augment_app_for_enum(
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let subcommands = variants.iter().map(|variant| {
        let name = variant.ident.to_string();
        let attrs = Attrs::from_struct(&variant.attrs, name);
        let app_var = syn::Ident::new("subcommand", proc_macro2::Span::call_site());
        let arg_block = match variant.fields {
            Named(ref fields) => gen_app_augmentation(&fields.named, &app_var),
            Unit => quote!( #app_var ),
            Unnamed(syn::FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                let ty = &unnamed[0];
                quote! {
                    {
                        let #app_var = <#ty>::augment_app(#app_var);
                        if <#ty>::is_subcommand() {
                            #app_var.setting(
                                ::clap::AppSettings::SubcommandRequiredElseHelp
                            )
                        } else {
                            #app_var
                        }
                    }
                }
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        let name = attrs.name();
        let from_attrs = attrs.methods();
        quote! {
            .subcommand({
                let #app_var = ::clap::App::new(#name);
                let #app_var = #arg_block;
                #app_var#from_attrs
            })
        }
    });

    quote! {
        pub fn augment_app<'b>(
            app: ::clap::App<'b>
        ) -> ::clap::App<'b> {
            app #( #subcommands )*
        }
    }
}

fn gen_from_subcommand(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let match_arms = variants.iter().map(|variant| {
        let attrs = Attrs::from_struct(&variant.attrs, variant.ident.to_string());
        let sub_name = attrs.name();
        let variant_name = &variant.ident;
        let constructor_block = match variant.fields {
            Named(ref fields) => from_argmatches::gen_constructor(&fields.named),
            Unit => quote!(),
            Unnamed(ref fields) if fields.unnamed.len() == 1 => {
                let ty = &fields.unnamed[0];
                quote!( ( <#ty as ::clap::FromArgMatches>::from_argmatches(matches) ) )
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        quote! {
            (#sub_name, Some(matches)) =>
                Some(#name :: #variant_name #constructor_block)
        }
    });

    quote! {
        pub fn from_subcommand<'b>(
            sub: (&'b str, Option<&'b ::clap::ArgMatches>)
        ) -> Option<Self> {
            match sub {
                #( #match_arms ),*,
                _ => None
            }
        }
    }
}

fn clap_impl_for_struct(
    name: &syn::Ident,
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_struct(name, attrs);
    let augment_app_fn = gen_augment_app_fn(fields);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_struct(name, fields);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #parse_fns

            pub fn is_subcommand() -> bool { false }
        }
    }
}

fn clap_impl_for_enum(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_enum(name, attrs);
    let augment_app_fn = gen_augment_app_for_enum(variants);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_enum(name);
    let from_subcommand = gen_from_subcommand(name, variants);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(unused_variables, dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #from_subcommand

            #parse_fns

            pub fn is_subcommand() -> bool { true }
        }
    }
}

pub fn derive_clap(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
    use syn::Data::*;

    let struct_name = &input.ident;
    let inner_impl = match input.data {
        Struct(syn::DataStruct {
            fields: syn::Fields::Named(ref fields),
            ..
        }) => clap_impl_for_struct(struct_name, &fields.named, &input.attrs),
        Enum(ref e) => clap_impl_for_enum(struct_name, &e.variants, &input.attrs),
        _ => panic!("clap_derive only supports non-tuple structs and enums"),
    };

    quote!(#inner_impl)
}

fn gen_parse_fns(name: &syn::Ident) -> proc_macro2::TokenStream {
    quote! {
        pub fn parse() -> #name {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches())
        }

        pub fn try_parse() -> ::std::result::Result<#name, ::clap::Error> {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().try_get_matches()?))
        }

        pub fn parse_from<I, T>(itr: I) -> #name
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches_from(itr))
        }

        pub fn try_parse_from<I, T>(itr: I) -> ::std::result::Result<#name, ::clap::Error>
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().try_get_matches_from(itr)?))
        }
    }
}
<|endoftext|>