<commit_before>#![warn(missing_docs)]
#![feature(slice_patterns)]

//! rebind
//! =========
//!
//! A library for binding input keys to actions, and modifying mouse behaviour. Keys can be
//! bound to actions, and then translated during runtime. `Keys` are mapped to `Actions` using
//! a `HashMap`, so lookup time is constant.

extern crate input;
extern crate itertools;
extern crate rustc_serialize;
extern crate viewport;
extern crate window;

mod builder;

#[cfg(test)]
mod test;

use input::{Input, Button, Motion};
use itertools::Itertools;
use std::cmp::{PartialEq, Eq, Ord};
use std::collections::HashMap;
use std::default::Default;
use std::fmt::{Debug, Formatter, Result};
use std::hash::Hash;
use viewport::Viewport;
use window::Size;

pub use builder::RebindBuilder;

/// Represents a logical action to be bound to a particular button press, e.g.
/// jump, attack, or move forward. Needs to be hashable, as it is used as a
/// lookup key when rebinding an action to a different button.
pub trait Action: Copy + Eq + Hash + Ord { }

/// A translated action.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Translated<A: Action> {
    /// A keypress event which was bound to an action
    Press(A),

    /// A key release event which was bound to an action
    Release(A),

    /// A translated mouse motion. The logical origin of a translated MouseCursor event
    /// is in the top left corner of the window, and the logical scroll is non-natural.
    /// Relative events are unchanged for now.
    Move(Motion)
}

/// A three-element tuple of Option<Button>. For simplicity, a maximum number of 3
/// buttons can be bound to each action, and this is exposed through the `InputRebind`
/// struct.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ButtonTuple(pub Option<Button>, pub Option<Button>, pub Option<Button>);

impl ButtonTuple {
    /// Creates a new tuple with no buttons in it (equivalent to `Default::default()`).
    pub fn new() -> Self { Default::default() }

    /// Check if the button is in the tuple.
    pub fn contains(&self, button: Button) -> bool {
        let sbtn = Some(button);
        self.0 == sbtn || self.1 == sbtn || self.2 == sbtn
    }

    /// Insert a button into the tuple if there is room, searching from left to right.
    /// If the button is inserted, returns true. Otherwise, if the button is not inserted,
    /// this function returns false.
    pub fn insert_inplace(&mut self, button: Button) -> bool {
        let sbtn = Some(button);
        match self {
            &mut ButtonTuple(a, b, c) if a.is_none() => {*self = ButtonTuple(sbtn, b, c); true},
            &mut ButtonTuple(a, b, c) if b.is_none() => {*self = ButtonTuple(a, sbtn, c); true},
            &mut ButtonTuple(a, b, c) if c.is_none() => {*self = ButtonTuple(a, b, sbtn); true}
            _ => false
        }
    }

    /// Returns an iterator over this tuple.
    pub fn iter(&self) -> ButtonTupleIter { (*self).into_iter() }
}

impl Default for ButtonTuple {
    /// Creates a new tuple with no buttons in it.
    fn default() -> Self { ButtonTuple(None, None, None) }
}

impl IntoIterator for ButtonTuple {
    type Item = Option<Button>;
    type IntoIter = ButtonTupleIter;

    fn into_iter(self) -> Self::IntoIter {
        ButtonTupleIter {
            button_tuple: self,
            i: 0
        }
    }
}

/// An iterator over a ButtonTuple.
pub struct ButtonTupleIter {
    button_tuple: ButtonTuple,
    i: usize
}

impl Iterator for ButtonTupleIter {
    type Item = Option<Button>;

    fn next(&mut self) -> Option<Self::Item> {
        let i = self.i;
        self.i += 1;
        match i {
            0 => Some(self.button_tuple.0),
            1 => Some(self.button_tuple.1),
            2 => Some(self.button_tuple.2),
            _ => None
        }
    }
}

/// An object which translates piston::input::Input events into input_map::Translated<A> events
#[derive(Clone, Debug, PartialEq)]
pub struct InputTranslator<A: Action> {
    keymap: HashMap<Button, A>,
    mouse_translator: MouseTranslator
}

impl<A: Action> InputTranslator<A> {
    /// Creates an empty InputTranslator.
    pub fn new(size: Size) -> Self {
        InputTranslator {
            keymap: HashMap::new(),
            mouse_translator: MouseTranslator::new(size)
        }
    }

    /// Translate an Input into a Translated<A> event. Returns `None` if there is no
    /// action associated with the `Input` variant.
    pub fn translate(&self, input: &Input) -> Option<Translated<A>> {
        macro_rules! translate_button(($but_state:ident, $but_var:ident) => (
            match self.keymap.get(&$but_var).cloned() {
                Some(act) => Some(Translated::$but_state(act)),
                None => None
            });
        );

        match input {
            &Input::Press(button) => translate_button!(Press, button),
            &Input::Release(button) => translate_button!(Release, button),
            &Input::Move(motion) =>
                Some(Translated::Move(self.mouse_translator.translate(motion))),
            _ => None
        }
    }

    /// Re-set the mouse bounds size used for calculating mouse events
    pub fn set_size(&mut self, size: Size) {
        self.mouse_translator.data.viewport_size = size
    }

    /// Re-set the mouse bounds size from a viewport
    pub fn set_size_from_viewport(&mut self, vp: Viewport) {
        self.set_size(Size::from(vp.draw_size));
    }
}

#[derive(Clone)]
struct MouseTranslationData {
    x_axis_motion_inverted: bool,
    y_axis_motion_inverted: bool,
    x_axis_scroll_inverted: bool,
    y_axis_scroll_inverted: bool,
    _sensitivity: f64,
    viewport_size: Size
}

impl MouseTranslationData {
    fn new(size: Size) -> Self {
        MouseTranslationData {
            x_axis_motion_inverted: false,
            y_axis_motion_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            _sensitivity: 0.0,
            viewport_size: size
        }
    }
}

impl Debug for MouseTranslationData {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}, {}, {}, {}, {}, ({}, {})",
               self.x_axis_motion_inverted,
               self.y_axis_motion_inverted,
               self.x_axis_scroll_inverted,
               self.y_axis_scroll_inverted,
               self._sensitivity,
               self.viewport_size.width,
               self.viewport_size.height)
    }
}

impl PartialEq for MouseTranslationData {
    fn eq(&self, other: &Self) -> bool {
        self.x_axis_motion_inverted == other.x_axis_motion_inverted &&
        self.y_axis_motion_inverted == other.y_axis_motion_inverted &&
        self.x_axis_scroll_inverted == other.x_axis_scroll_inverted &&
        self.y_axis_scroll_inverted == other.y_axis_scroll_inverted &&
        self._sensitivity == other._sensitivity &&
        self.viewport_size.width    == other.viewport_size.width &&
        self.viewport_size.height   == other.viewport_size.height
    }
}

#[derive(Clone, Debug, PartialEq)]
struct MouseTranslator {
    data: MouseTranslationData
}

impl MouseTranslator {
    fn new(size: Size) -> Self {
        MouseTranslator {
            data: MouseTranslationData::new(size)
        }
    }

    fn translate(&self, motion: Motion) -> Motion {
        match motion {
            Motion::MouseCursor(x, y) => {
                let (sw, sh) = {
                    let Size {width, height} = self.data.viewport_size;
                    (width as f64, height as f64)
                };

                let cx = if self.data.x_axis_motion_inverted { sw - x } else { x };
                let cy = if self.data.y_axis_motion_inverted { sh - y } else { y };

                Motion::MouseCursor(cx, cy)
            },
            Motion::MouseScroll(x, y) => {
                let mx = if self.data.x_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                let my = if self.data.y_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                Motion::MouseScroll(x * mx, y * my)
            },
            relative => relative
        }
    }
}

/// An interface for rebinding keys to actions. This is freely convertable to and
/// from an InputTranslator.
#[derive(Clone, Debug, PartialEq)]
pub struct InputRebind<A: Action> {
    keymap: HashMap<A, ButtonTuple>,
    mouse_data: MouseTranslationData
}

impl<A: Action> InputRebind<A> {
    /// Creates a new InputRebind with no stored Action/ButtonTuple pairs.
    pub fn new(size: Size) -> Self {
        InputRebind {
            keymap: HashMap::new(),
            mouse_data: MouseTranslationData::new(size)
        }
    }

    /// Insert an Action into this InputRebind. If the Action is already in the
    /// InputRebind, then its ButtonTuple will be reset to (None, None, None), and
    /// the old ButtonTuple will be returned.
    pub fn insert_action(&mut self, action: A) -> Option<ButtonTuple> {
        self.keymap.insert(action, ButtonTuple::new())
    }

    /// Insert an Action into this InputRebind, and assign it to the ButtonTuple.
    /// If the Action is already in the InputRebind, the old ButtonTuple will be
    /// returned.
    pub fn insert_action_with_buttons(&mut self, action: A, buttons: ButtonTuple) -> Option<ButtonTuple> {
        self.keymap.insert(action, buttons)
    }

    /// Return a reference to the current ButtonTuple stored for an action. If the action
    /// is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings(&self, action: &A) -> Option<&ButtonTuple> {
        self.keymap.get(action)
    }

    /// Returns a mutable reference to the current ButtonTuple stored for an action. If the
    /// action is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings_mut(&mut self, action: &mut A) -> Option<&mut ButtonTuple> {
        self.keymap.get_mut(action)
    }

    /// Returns a reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the x axis is
    /// inverted.
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// x axis is inverted.
    pub fn get_x_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the y axis is
    /// inverted.
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// y axis is inverted.
    pub fn get_y_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a reference to the currently stored viewport size used for calculating the imaginary mouse
    /// position.
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    /// Returns a mutable reference to the currently stored viewport size used for calculating the imaginary
    /// mouse position.
    pub fn get_viewport_size_mut(&mut self) -> &mut Size {
        &mut self.mouse_data.viewport_size
    }
}

impl<A: Action> Default for InputRebind<A> {
    /// Creates an `InputRebind` with no pairs. In addition, the viewport size is set to [800, 600].
    fn default() -> Self {
        InputRebind::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for InputRebind<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_translator = InputTranslator::new(self.mouse_data.viewport_size);
        input_translator.mouse_translator.data = self.mouse_data;
        let key_vec = self.keymap.values()
                                 .flat_map(|bt| bt.into_iter().filter_map(|x| x))
                                 .collect::<Vec<_>>();

        input_translator.keymap.reserve(key_vec.len());
        for &k in &key_vec {
            for (&a, bt) in self.keymap.iter() {
                if bt.contains(k) {
                    input_translator.keymap.insert(k, a);
                }
            }
        }

        input_translator
    }
}

impl<A: Action> Into<InputRebind<A>> for InputTranslator<A> {
    fn into(self) -> InputRebind<A> {
        let mut input_rebind = InputRebind::new(self.mouse_translator.data.viewport_size);
        input_rebind.mouse_data = self.mouse_translator.data;
        input_rebind.keymap = self.keymap.iter()
                                         .map(|(k, v)| (*v, vec![Some(*k)]))
                                         .sorted_by(|&(v0, _), &(v1, _)| Ord::cmp(&v0, &v1))
                                         .into_iter()
                                         .coalesce(|(k0, v0), (k1, v1)| if k0 == k1 {
                                                 Ok((k0, v0.into_iter().chain(v1).collect()))
                                             } else {
                                                 Err(((k0, v0), (k1, v1)))
                                             })
                                         .map(|(k, v)| if let [b0, b1, b2] = &v.iter()
                                                                               .cloned()
                                                                               .pad_using(3, |_| None)
                                                                               .take(3)
                                                                               .collect::<Vec<_>>()[..] {
                                                  (k, ButtonTuple(b0, b1, b2))
                                             } else {
                                                 unreachable!();
                                             })
                                         .collect();

        input_rebind
    }
}
<commit_msg>Add methods to convert `InputTranslator` and InputRebind` between each other without using the `Into` trait<commit_after>#![warn(missing_docs)]
#![feature(slice_patterns)]

//! rebind
//! =========
//!
//! A library for binding input keys to actions, and modifying mouse behaviour. Keys can be
//! bound to actions, and then translated during runtime. `Keys` are mapped to `Actions` using
//! a `HashMap`, so lookup time is constant.

extern crate input;
extern crate itertools;
extern crate rustc_serialize;
extern crate viewport;
extern crate window;

mod builder;

#[cfg(test)]
mod test;

use input::{Input, Button, Motion};
use itertools::Itertools;
use std::cmp::{PartialEq, Eq, Ord};
use std::collections::HashMap;
use std::default::Default;
use std::fmt::{Debug, Formatter, Result};
use std::hash::Hash;
use viewport::Viewport;
use window::Size;

pub use builder::RebindBuilder;

/// Represents a logical action to be bound to a particular button press, e.g.
/// jump, attack, or move forward. Needs to be hashable, as it is used as a
/// lookup key when rebinding an action to a different button.
pub trait Action: Copy + Eq + Hash + Ord { }

/// A translated action.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Translated<A: Action> {
    /// A keypress event which was bound to an action
    Press(A),

    /// A key release event which was bound to an action
    Release(A),

    /// A translated mouse motion. The logical origin of a translated MouseCursor event
    /// is in the top left corner of the window, and the logical scroll is non-natural.
    /// Relative events are unchanged for now.
    Move(Motion)
}

/// A three-element tuple of Option<Button>. For simplicity, a maximum number of 3
/// buttons can be bound to each action, and this is exposed through the `InputRebind`
/// struct.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ButtonTuple(pub Option<Button>, pub Option<Button>, pub Option<Button>);

impl ButtonTuple {
    /// Creates a new tuple with no buttons in it (equivalent to `Default::default()`).
    pub fn new() -> Self { Default::default() }

    /// Check if the button is in the tuple.
    pub fn contains(&self, button: Button) -> bool {
        let sbtn = Some(button);
        self.0 == sbtn || self.1 == sbtn || self.2 == sbtn
    }

    /// Insert a button into the tuple if there is room, searching from left to right.
    /// If the button is inserted, returns true. Otherwise, if the button is not inserted,
    /// this function returns false.
    pub fn insert_inplace(&mut self, button: Button) -> bool {
        let sbtn = Some(button);
        match self {
            &mut ButtonTuple(a, b, c) if a.is_none() => {*self = ButtonTuple(sbtn, b, c); true},
            &mut ButtonTuple(a, b, c) if b.is_none() => {*self = ButtonTuple(a, sbtn, c); true},
            &mut ButtonTuple(a, b, c) if c.is_none() => {*self = ButtonTuple(a, b, sbtn); true}
            _ => false
        }
    }

    /// Returns an iterator over this tuple.
    pub fn iter(&self) -> ButtonTupleIter { (*self).into_iter() }
}

impl Default for ButtonTuple {
    /// Creates a new tuple with no buttons in it.
    fn default() -> Self { ButtonTuple(None, None, None) }
}

impl IntoIterator for ButtonTuple {
    type Item = Option<Button>;
    type IntoIter = ButtonTupleIter;

    fn into_iter(self) -> Self::IntoIter {
        ButtonTupleIter {
            button_tuple: self,
            i: 0
        }
    }
}

/// An iterator over a ButtonTuple.
pub struct ButtonTupleIter {
    button_tuple: ButtonTuple,
    i: usize
}

impl Iterator for ButtonTupleIter {
    type Item = Option<Button>;

    fn next(&mut self) -> Option<Self::Item> {
        let i = self.i;
        self.i += 1;
        match i {
            0 => Some(self.button_tuple.0),
            1 => Some(self.button_tuple.1),
            2 => Some(self.button_tuple.2),
            _ => None
        }
    }
}

/// An object which translates piston::input::Input events into input_map::Translated<A> events
#[derive(Clone, Debug, PartialEq)]
pub struct InputTranslator<A: Action> {
    keymap: HashMap<Button, A>,
    mouse_translator: MouseTranslator
}

impl<A: Action> InputTranslator<A> {
    /// Creates an empty InputTranslator.
    pub fn new(size: Size) -> Self {
        InputTranslator {
            keymap: HashMap::new(),
            mouse_translator: MouseTranslator::new(size)
        }
    }

    /// Translate an Input into a Translated<A> event. Returns `None` if there is no
    /// action associated with the `Input` variant.
    pub fn translate(&self, input: &Input) -> Option<Translated<A>> {
        macro_rules! translate_button(($but_state:ident, $but_var:ident) => (
            match self.keymap.get(&$but_var).cloned() {
                Some(act) => Some(Translated::$but_state(act)),
                None => None
            });
        );

        match input {
            &Input::Press(button) => translate_button!(Press, button),
            &Input::Release(button) => translate_button!(Release, button),
            &Input::Move(motion) =>
                Some(Translated::Move(self.mouse_translator.translate(motion))),
            _ => None
        }
    }

    /// Re-set the mouse bounds size used for calculating mouse events
    pub fn set_size(&mut self, size: Size) {
        self.mouse_translator.data.viewport_size = size
    }

    /// Re-set the mouse bounds size from a viewport
    pub fn set_size_from_viewport(&mut self, vp: Viewport) {
        self.set_size(Size::from(vp.draw_size));
    }

    /// Convert the `InputTranslator` into an `InputRebind`. Consumes the
    /// `InputTranslator`.
    pub fn into_rebind(self) -> InputRebind<A> { self.into() }
}

#[derive(Clone)]
struct MouseTranslationData {
    x_axis_motion_inverted: bool,
    y_axis_motion_inverted: bool,
    x_axis_scroll_inverted: bool,
    y_axis_scroll_inverted: bool,
    _sensitivity: f64,
    viewport_size: Size
}

impl MouseTranslationData {
    fn new(size: Size) -> Self {
        MouseTranslationData {
            x_axis_motion_inverted: false,
            y_axis_motion_inverted: false,
            x_axis_scroll_inverted: false,
            y_axis_scroll_inverted: false,
            _sensitivity: 0.0,
            viewport_size: size
        }
    }
}

impl Debug for MouseTranslationData {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}, {}, {}, {}, {}, ({}, {})",
               self.x_axis_motion_inverted,
               self.y_axis_motion_inverted,
               self.x_axis_scroll_inverted,
               self.y_axis_scroll_inverted,
               self._sensitivity,
               self.viewport_size.width,
               self.viewport_size.height)
    }
}

impl PartialEq for MouseTranslationData {
    fn eq(&self, other: &Self) -> bool {
        self.x_axis_motion_inverted == other.x_axis_motion_inverted &&
        self.y_axis_motion_inverted == other.y_axis_motion_inverted &&
        self.x_axis_scroll_inverted == other.x_axis_scroll_inverted &&
        self.y_axis_scroll_inverted == other.y_axis_scroll_inverted &&
        self._sensitivity == other._sensitivity &&
        self.viewport_size.width    == other.viewport_size.width &&
        self.viewport_size.height   == other.viewport_size.height
    }
}

#[derive(Clone, Debug, PartialEq)]
struct MouseTranslator {
    data: MouseTranslationData
}

impl MouseTranslator {
    fn new(size: Size) -> Self {
        MouseTranslator {
            data: MouseTranslationData::new(size)
        }
    }

    fn translate(&self, motion: Motion) -> Motion {
        match motion {
            Motion::MouseCursor(x, y) => {
                let (sw, sh) = {
                    let Size {width, height} = self.data.viewport_size;
                    (width as f64, height as f64)
                };

                let cx = if self.data.x_axis_motion_inverted { sw - x } else { x };
                let cy = if self.data.y_axis_motion_inverted { sh - y } else { y };

                Motion::MouseCursor(cx, cy)
            },
            Motion::MouseScroll(x, y) => {
                let mx = if self.data.x_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                let my = if self.data.y_axis_scroll_inverted { -1.0f64 } else { 1.0 };
                Motion::MouseScroll(x * mx, y * my)
            },
            relative => relative
        }
    }
}

/// An interface for rebinding keys to actions. This is freely convertable to and
/// from an InputTranslator.
#[derive(Clone, Debug, PartialEq)]
pub struct InputRebind<A: Action> {
    keymap: HashMap<A, ButtonTuple>,
    mouse_data: MouseTranslationData
}

impl<A: Action> InputRebind<A> {
    /// Creates a new InputRebind with no stored Action/ButtonTuple pairs.
    pub fn new(size: Size) -> Self {
        InputRebind {
            keymap: HashMap::new(),
            mouse_data: MouseTranslationData::new(size)
        }
    }

    /// Insert an Action into this InputRebind. If the Action is already in the
    /// InputRebind, then its ButtonTuple will be reset to (None, None, None), and
    /// the old ButtonTuple will be returned.
    pub fn insert_action(&mut self, action: A) -> Option<ButtonTuple> {
        self.keymap.insert(action, ButtonTuple::new())
    }

    /// Insert an Action into this InputRebind, and assign it to the ButtonTuple.
    /// If the Action is already in the InputRebind, the old ButtonTuple will be
    /// returned.
    pub fn insert_action_with_buttons(&mut self, action: A, buttons: ButtonTuple) -> Option<ButtonTuple> {
        self.keymap.insert(action, buttons)
    }

    /// Return a reference to the current ButtonTuple stored for an action. If the action
    /// is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings(&self, action: &A) -> Option<&ButtonTuple> {
        self.keymap.get(action)
    }

    /// Returns a mutable reference to the current ButtonTuple stored for an action. If the
    /// action is not stored in this InputRebind, then `None` will be returned.
    pub fn get_bindings_mut(&mut self, action: &mut A) -> Option<&mut ButtonTuple> {
        self.keymap.get_mut(action)
    }

    /// Returns a reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether x axis scrolling is inverted.
    pub fn get_x_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether y axis scrolling is inverted.
    pub fn get_y_scroll_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_scroll_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the x axis is
    /// inverted.
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// x axis is inverted.
    pub fn get_x_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.x_axis_motion_inverted
    }

    /// Returns a reference to the boolean which represents whether mouse movement along the y axis is
    /// inverted.
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a mutable reference to the boolean which represents whether mouse movement along the
    /// y axis is inverted.
    pub fn get_y_motion_inverted_mut(&mut self) -> &mut bool {
        &mut self.mouse_data.y_axis_motion_inverted
    }

    /// Returns a reference to the currently stored viewport size used for calculating the imaginary mouse
    /// position.
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    /// Returns a mutable reference to the currently stored viewport size used for calculating the imaginary
    /// mouse position.
    pub fn get_viewport_size_mut(&mut self) -> &mut Size {
        &mut self.mouse_data.viewport_size
    }

    /// Convert the `InputRebind` into an `InputTranslator`. Consumes the
    /// `InputRebind`.
    pub fn into_translator(self) -> InputTranslator<A> { self.into() }
}

impl<A: Action> Default for InputRebind<A> {
    /// Creates an `InputRebind` with no pairs. In addition, the viewport size is set to [800, 600].
    fn default() -> Self {
        InputRebind::new((800, 600).into())
    }
}

impl<A: Action> Into<InputTranslator<A>> for InputRebind<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_translator = InputTranslator::new(self.mouse_data.viewport_size);
        input_translator.mouse_translator.data = self.mouse_data;
        let key_vec = self.keymap.values()
                                 .flat_map(|bt| bt.into_iter().filter_map(|x| x))
                                 .collect::<Vec<_>>();

        input_translator.keymap.reserve(key_vec.len());
        for &k in &key_vec {
            for (&a, bt) in self.keymap.iter() {
                if bt.contains(k) {
                    input_translator.keymap.insert(k, a);
                }
            }
        }

        input_translator
    }
}

impl<A: Action> Into<InputRebind<A>> for InputTranslator<A> {
    fn into(self) -> InputRebind<A> {
        let mut input_rebind = InputRebind::new(self.mouse_translator.data.viewport_size);
        input_rebind.mouse_data = self.mouse_translator.data;
        input_rebind.keymap = self.keymap.iter()
                                         .map(|(k, v)| (*v, vec![Some(*k)]))
                                         .sorted_by(|&(v0, _), &(v1, _)| Ord::cmp(&v0, &v1))
                                         .into_iter()
                                         .coalesce(|(k0, v0), (k1, v1)| if k0 == k1 {
                                                 Ok((k0, v0.into_iter().chain(v1).collect()))
                                             } else {
                                                 Err(((k0, v0), (k1, v1)))
                                             })
                                         .map(|(k, v)| if let [b0, b1, b2] = &v.iter()
                                                                               .cloned()
                                                                               .pad_using(3, |_| None)
                                                                               .take(3)
                                                                               .collect::<Vec<_>>()[..] {
                                                  (k, ButtonTuple(b0, b1, b2))
                                             } else {
                                                 unreachable!();
                                             })
                                         .collect();

        input_rebind
    }
}
<|endoftext|>


<commit_before>//! This crate implements a structure that can be used as a generic array type.use
//! Core Rust array types `[T; N]` can't be used generically with respect to `N`, so for example this:
//!
//! ```{should_fail}
//! struct Foo<T, N> {
//!     data: [T; N]
//! }
//! ```
//!
//! won't work.
//!
//! **generic-array** exports a `GenericArray<T,N>` type, which lets the above be implemented as:
//!
//! ```
//!# use generic_array::{ArrayLength, GenericArray};
//! struct Foo<T, N: ArrayLength<T>> {
//!     data: GenericArray<T,N>
//! }
//! ```
//!
//! The `ArrayLength<T>` trait is implemented by default for [unsigned integer types](../typenum/uint/index.html) from [typenum](../typenum/index.html).
//!
//! For ease of use, an `arr!` macro is provided - example below:
//!
//! ```
//! # #[macro_use]
//! # extern crate generic_array;
//! # extern crate typenum;
//! # fn main() {
//! let array = arr![u32; 1, 2, 3];
//! assert_eq!(array[2], 3);
//! # }
//! ```
#![no_std]
extern crate core as std;
pub extern crate typenum;
extern crate nodrop;
#[cfg(feature="serde")]
extern crate serde;
pub mod arr;
pub mod iter;
pub use iter::GenericArrayIter;

#[cfg(feature="serde")]
pub mod impl_serde;

use nodrop::NoDrop;
use typenum::uint::{Unsigned, UTerm, UInt};
use typenum::bit::{B0, B1};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;
use std::slice;

/// Trait making `GenericArray` work, marking types to be used as length of an array
pub unsafe trait ArrayLength<T> : Unsigned {
    /// Associated type representing the array type for the number
    type ArrayType;
}

unsafe impl<T> ArrayLength<T> for UTerm {
    type ArrayType = ();
}

/// Internal type used to generate a struct of appropriate size
#[allow(dead_code)]
#[repr(C)]
pub struct GenericArrayImplEven<T, U> {
    parent1: U,
    parent2: U,
    _marker: PhantomData<T>
}

impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
    fn clone(&self) -> GenericArrayImplEven<T, U> {
        GenericArrayImplEven {
            parent1: self.parent1.clone(),
            parent2: self.parent2.clone(),
            _marker: PhantomData
        }
    }
}

impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}

/// Internal type used to generate a struct of appropriate size
#[allow(dead_code)]
#[repr(C)]
pub struct GenericArrayImplOdd<T, U> {
    parent1: U,
    parent2: U,
    data: T
}

impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
    fn clone(&self) -> GenericArrayImplOdd<T, U> {
        GenericArrayImplOdd {
            parent1: self.parent1.clone(),
            parent2: self.parent2.clone(),
            data: self.data.clone()
        }
    }
}

impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}

unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
}

unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
}

/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
#[allow(dead_code)]
pub struct GenericArray<T, U: ArrayLength<T>> {
    data: U::ArrayType
}

impl<T, N> Deref for GenericArray<T, N> where N: ArrayLength<T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        unsafe {
            slice::from_raw_parts(self as *const Self as *const T, N::to_usize())
        }
    }
}

impl<T, N> DerefMut for GenericArray<T, N> where N: ArrayLength<T> {
    fn deref_mut(&mut self) -> &mut [T] {
        unsafe {
            slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize())
        }
    }
}

impl<T, N> GenericArray<T, N> where N: ArrayLength<T> {
    /// map a function over a  slice to a `GenericArray`.
    /// The length of the slice *must* be equal to the length of the array
    pub fn map_slice<S, F: Fn(&S) -> T>(s: &[S], f: F) -> GenericArray<T, N> {
        assert_eq!(s.len(), N::to_usize());
        map_inner(s, f)
    }

    /// map a function over a `GenericArray`.
    pub fn map<U, F>(self, f: F) -> GenericArray<U, N>
    where F: Fn(&T) -> U, N: ArrayLength<U> {
        map_inner(&self, f)
    }
}

#[inline]
fn map_inner<S, F, T, N>(list: &[S], f: F) -> GenericArray<T, N>
where F: Fn(&S) -> T, N: ArrayLength<T> {
     unsafe {
        let mut res : NoDrop<GenericArray<T, N>> =
                      NoDrop::new(mem::uninitialized());
        for (s, r) in list.iter().zip(res.iter_mut()) {
            std::ptr::write(r, f(s))
        }
        res.into_inner()
    }
}

impl<T: Default, N> GenericArray<T, N> where N: ArrayLength<T> {

    /// Function constructing an array filled with default values
    pub fn new() -> GenericArray<T, N> {
        unsafe {
            let mut res : NoDrop<GenericArray<T, N>> =
                          NoDrop::new(mem::uninitialized());
            for r in res.iter_mut() {
                ptr::write(r, T::default())
            }
            res.into_inner()
        }
    }

}

impl<T: Default, N> Default for GenericArray<T, N> where N: ArrayLength<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T: Clone, N> GenericArray<T, N> where N: ArrayLength<T> {

    /// Function constructing an array from a slice; the length of the slice must be equal to the length of the array
    pub fn from_slice(list: &[T]) -> GenericArray<T, N> {
        assert_eq!(list.len(), N::to_usize());
        map_inner(list, |x: &T| x.clone())
    }

}

impl<T: Clone, N> Clone for GenericArray<T, N> where N: ArrayLength<T> {
    fn clone(&self) -> GenericArray<T, N> {
        unsafe {
            let mut res : NoDrop<GenericArray<T, N>> =
                          NoDrop::new(mem::uninitialized());
            for i in 0..N::to_usize() { ptr::write(&mut res[i], self[i].clone()) }
            res.into_inner()
        }
    }
}
impl<T: Copy, N> Copy for GenericArray<T, N> where N: ArrayLength<T>, N::ArrayType: Copy {}

impl<T: PartialEq, N> PartialEq for GenericArray<T, N> where N: ArrayLength<T> {
    fn eq(&self, other: &Self) -> bool { **self == **other }
}
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}

impl<T: Debug, N> Debug for GenericArray<T, N> where N: ArrayLength<T> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { self[..].fmt(fmt) }
}
<commit_msg>Add as_slice, as_mut_slice, as_bytes<commit_after>//! This crate implements a structure that can be used as a generic array type.use
//! Core Rust array types `[T; N]` can't be used generically with respect to `N`, so for example this:
//!
//! ```{should_fail}
//! struct Foo<T, N> {
//!     data: [T; N]
//! }
//! ```
//!
//! won't work.
//!
//! **generic-array** exports a `GenericArray<T,N>` type, which lets the above be implemented as:
//!
//! ```
//!# use generic_array::{ArrayLength, GenericArray};
//! struct Foo<T, N: ArrayLength<T>> {
//!     data: GenericArray<T,N>
//! }
//! ```
//!
//! The `ArrayLength<T>` trait is implemented by default for [unsigned integer types](../typenum/uint/index.html) from [typenum](../typenum/index.html).
//!
//! For ease of use, an `arr!` macro is provided - example below:
//!
//! ```
//! # #[macro_use]
//! # extern crate generic_array;
//! # extern crate typenum;
//! # fn main() {
//! let array = arr![u32; 1, 2, 3];
//! assert_eq!(array[2], 3);
//! # }
//! ```
#![no_std]
extern crate core as std;
pub extern crate typenum;
extern crate nodrop;
#[cfg(feature="serde")]
extern crate serde;
pub mod arr;
pub mod iter;
pub use iter::GenericArrayIter;

#[cfg(feature="serde")]
pub mod impl_serde;

use nodrop::NoDrop;
use typenum::uint::{Unsigned, UTerm, UInt};
use typenum::bit::{B0, B1};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;
use std::slice;

/// Trait making `GenericArray` work, marking types to be used as length of an array
pub unsafe trait ArrayLength<T> : Unsigned {
    /// Associated type representing the array type for the number
    type ArrayType;
}

unsafe impl<T> ArrayLength<T> for UTerm {
    type ArrayType = ();
}

/// Internal type used to generate a struct of appropriate size
#[allow(dead_code)]
#[repr(C)]
pub struct GenericArrayImplEven<T, U> {
    parent1: U,
    parent2: U,
    _marker: PhantomData<T>
}

impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
    fn clone(&self) -> GenericArrayImplEven<T, U> {
        GenericArrayImplEven {
            parent1: self.parent1.clone(),
            parent2: self.parent2.clone(),
            _marker: PhantomData
        }
    }
}

impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}

/// Internal type used to generate a struct of appropriate size
#[allow(dead_code)]
#[repr(C)]
pub struct GenericArrayImplOdd<T, U> {
    parent1: U,
    parent2: U,
    data: T
}

impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
    fn clone(&self) -> GenericArrayImplOdd<T, U> {
        GenericArrayImplOdd {
            parent1: self.parent1.clone(),
            parent2: self.parent2.clone(),
            data: self.data.clone()
        }
    }
}

impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}

unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
}

unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
}

/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
#[allow(dead_code)]
pub struct GenericArray<T, U: ArrayLength<T>> {
    data: U::ArrayType
}

impl<T, N> Deref for GenericArray<T, N> where N: ArrayLength<T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        unsafe {
            slice::from_raw_parts(self as *const Self as *const T, N::to_usize())
        }
    }
}

impl<T, N> DerefMut for GenericArray<T, N> where N: ArrayLength<T> {
    fn deref_mut(&mut self) -> &mut [T] {
        unsafe {
            slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize())
        }
    }
}

impl<T, N> GenericArray<T, N> where N: ArrayLength<T> {
    /// map a function over a  slice to a `GenericArray`.
    /// The length of the slice *must* be equal to the length of the array
    pub fn map_slice<S, F: Fn(&S) -> T>(s: &[S], f: F) -> GenericArray<T, N> {
        assert_eq!(s.len(), N::to_usize());
        map_inner(s, f)
    }

    /// map a function over a `GenericArray`.
    pub fn map<U, F>(self, f: F) -> GenericArray<U, N>
    where F: Fn(&T) -> U, N: ArrayLength<U> {
        map_inner(&self, f)
    }

    /// Extracts a slice containing the entire array
    pub fn as_slice(&self) -> &[T] {
        self.deref()
    }

    /// Extracts a mutable slice containing the entire array
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        self.deref_mut()
    }

    /// Allows access to the data in the array as a slice of bytes
    pub fn as_bytes(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(self as *const Self as *const u8,
                                  N::to_usize() * mem::size_of::<T>())
        }
    }
}

#[inline]
fn map_inner<S, F, T, N>(list: &[S], f: F) -> GenericArray<T, N>
where F: Fn(&S) -> T, N: ArrayLength<T> {
     unsafe {
        let mut res : NoDrop<GenericArray<T, N>> =
                      NoDrop::new(mem::uninitialized());
        for (s, r) in list.iter().zip(res.iter_mut()) {
            std::ptr::write(r, f(s))
        }
        res.into_inner()
    }
}

impl<T: Default, N> GenericArray<T, N> where N: ArrayLength<T> {

    /// Function constructing an array filled with default values
    pub fn new() -> GenericArray<T, N> {
        unsafe {
            let mut res : NoDrop<GenericArray<T, N>> =
                          NoDrop::new(mem::uninitialized());
            for r in res.iter_mut() {
                ptr::write(r, T::default())
            }
            res.into_inner()
        }
    }

}

impl<T: Default, N> Default for GenericArray<T, N> where N: ArrayLength<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T: Clone, N> GenericArray<T, N> where N: ArrayLength<T> {

    /// Function constructing an array from a slice; the length of the slice must be equal to the length of the array
    pub fn from_slice(list: &[T]) -> GenericArray<T, N> {
        assert_eq!(list.len(), N::to_usize());
        map_inner(list, |x: &T| x.clone())
    }

}

impl<T: Clone, N> Clone for GenericArray<T, N> where N: ArrayLength<T> {
    fn clone(&self) -> GenericArray<T, N> {
        unsafe {
            let mut res : NoDrop<GenericArray<T, N>> =
                          NoDrop::new(mem::uninitialized());
            for i in 0..N::to_usize() { ptr::write(&mut res[i], self[i].clone()) }
            res.into_inner()
        }
    }
}
impl<T: Copy, N> Copy for GenericArray<T, N> where N: ArrayLength<T>, N::ArrayType: Copy {}

impl<T: PartialEq, N> PartialEq for GenericArray<T, N> where N: ArrayLength<T> {
    fn eq(&self, other: &Self) -> bool { **self == **other }
}
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}

impl<T: Debug, N> Debug for GenericArray<T, N> where N: ArrayLength<T> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { self[..].fmt(fmt) }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

/*!
Syntax extension to create floating point literals from hexadecimal strings

Once loaded, hexfloat!() is called with a string containing the hexadecimal
floating-point literal, and an optional type (f32 or f64).
If the type is omitted, the literal is treated the same as a normal unsuffixed
literal.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(plugin)]
extern crate hexfloat;

fn main() {
    let val = hexfloat!("0x1.ffffb4", f32);
}
```

# References

* [ExploringBinary: hexadecimal floating point constants]
  (http://www.exploringbinary.com/hexadecimal-floating-point-constants/)

*/

#![crate_name = "hexfloat"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("hexfloat", expand_syntax_ext);
}

//Check if the literal is valid (as LLVM expects),
//and return a descriptive error if not.
fn hex_float_lit_err(s: &str) -> Option<(uint, String)> {
    let mut chars = s.chars().peekable();
    let mut i = 0;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    if chars.next() != Some('0') {
        return Some((i, "Expected '0'".to_string()));
    } i+=1;
    if chars.next() != Some('x') {
        return Some((i, "Expected 'x'".to_string()));
    } i+=1;
    let mut d_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;}
    if chars.next() != Some('.') {
        return Some((i, "Expected '.'".to_string()));
    } i+=1;
    let mut f_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;}
    if d_len == 0 && f_len == 0 {
        return Some((i, "Expected digits before or after decimal \
                         point".to_string()));
    }
    if chars.next() != Some('p') {
        return Some((i, "Expected 'p'".to_string()));
    } i+=1;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    let mut e_len = 0i;
    for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1}
    if e_len == 0 {
        return Some((i, "Expected exponent digits".to_string()));
    }
    match chars.next() {
        None => None,
        Some(_) => Some((i, "Expected end of string".to_string()))
    }
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult + 'static> {
    let (expr, ty_lit) = parse_tts(cx, tts);

    let ty = match ty_lit {
        None => None,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "f32" => Some(ast::TyF32),
            "f64" => Some(ast::TyF64),
            _ => {
                cx.span_err(span, "invalid floating point type in hexfloat!");
                None
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                s.clone()
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in hexfloat!");
                return base::DummyResult::expr(sp);
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in hexfloat!");
            return base::DummyResult::expr(sp);
        }
    };

    {
        let err = hex_float_lit_err(s.get());
        match err {
            Some((err_pos, err_str)) => {
                let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
                let span = syntax::codemap::mk_sp(pos,pos);
                cx.span_err(span,
                            format!("invalid hex float literal in hexfloat!: \
                                     {}",
                                    err_str).as_slice());
                return base::DummyResult::expr(sp);
            }
            _ => ()
        }
    }

    let lit = match ty {
        None => ast::LitFloatUnsuffixed(s),
        Some (ty) => ast::LitFloat(s, ty)
    };
    MacExpr::new(cx.expr_lit(sp, lit))
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt,
             tts: &[ast::TokenTree]) -> (P<ast::Expr>, Option<Ident>) {
    let p = &mut cx.new_parser_from_tts(tts);
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>Update to rust master<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

/*!
Syntax extension to create floating point literals from hexadecimal strings

Once loaded, hexfloat!() is called with a string containing the hexadecimal
floating-point literal, and an optional type (f32 or f64).
If the type is omitted, the literal is treated the same as a normal unsuffixed
literal.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(plugin)]
extern crate hexfloat;

fn main() {
    let val = hexfloat!("0x1.ffffb4", f32);
}
```

# References

* [ExploringBinary: hexadecimal floating point constants]
  (http://www.exploringbinary.com/hexadecimal-floating-point-constants/)

*/

#![crate_name = "hexfloat"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("hexfloat", expand_syntax_ext);
}

//Check if the literal is valid (as LLVM expects),
//and return a descriptive error if not.
fn hex_float_lit_err(s: &str) -> Option<(uint, String)> {
    let mut chars = s.chars().peekable();
    let mut i = 0;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    if chars.next() != Some('0') {
        return Some((i, "Expected '0'".to_string()));
    } i+=1;
    if chars.next() != Some('x') {
        return Some((i, "Expected 'x'".to_string()));
    } i+=1;
    let mut d_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;}
    if chars.next() != Some('.') {
        return Some((i, "Expected '.'".to_string()));
    } i+=1;
    let mut f_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;}
    if d_len == 0 && f_len == 0 {
        return Some((i, "Expected digits before or after decimal \
                         point".to_string()));
    }
    if chars.next() != Some('p') {
        return Some((i, "Expected 'p'".to_string()));
    } i+=1;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    let mut e_len = 0i;
    for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1}
    if e_len == 0 {
        return Some((i, "Expected exponent digits".to_string()));
    }
    match chars.next() {
        None => None,
        Some(_) => Some((i, "Expected end of string".to_string()))
    }
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult + 'static> {
    let (expr, ty_lit) = parse_tts(cx, tts);

    let ty = match ty_lit {
        None => None,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "f32" => Some(ast::TyF32),
            "f64" => Some(ast::TyF64),
            _ => {
                cx.span_err(span, "invalid floating point type in hexfloat!");
                None
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                s.clone()
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in hexfloat!");
                return base::DummyResult::expr(sp);
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in hexfloat!");
            return base::DummyResult::expr(sp);
        }
    };

    {
        let err = hex_float_lit_err(s.get());
        match err {
            Some((err_pos, err_str)) => {
                let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
                let span = syntax::codemap::mk_sp(pos,pos);
                cx.span_err(span,
                            format!("invalid hex float literal in hexfloat!: \
                                     {}",
                                    err_str).as_slice());
                return base::DummyResult::expr(sp);
            }
            _ => ()
        }
    }

    let lit = match ty {
        None => ast::LitFloatUnsuffixed(s),
        Some (ty) => ast::LitFloat(s, ty)
    };
    MacExpr::new(cx.expr_lit(sp, lit))
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt,
             tts: &[ast::TokenTree]) -> (P<ast::Expr>, Option<Ident>) {
    let p = &mut cx.new_parser_from_tts(tts);
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>


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

//! # GTK+ 3 bindings
//!
//! This library contains safe Rust bindings for [GTK+ 3](http://www.gtk.org), a
//! multi-platform GUI toolkit. It's a part of [Gtk-rs](http://gtk-rs.org/).
//!
//! The library is a work in progress: expect missing bindings and breaking
//! changes. A steadily increasing share of the code is machine-generated from
//! GObject introspection metadata. The API docs were converted from the
//! upstream ones so until they've all been reviewed there will be incongruities
//! with actual Rust APIs.
//!
//! See also:
//!
//! - [Gtk-rs documentation overview](http://gtk-rs.org/docs/)
//!
//! - [General GLib family types and object system overview](../glib/index.html)
//!
//! - [GTK+ documentation](http://www.gtk.org/documentation.php)
//!
//! # Hello World
//!
//! ```no_run
//! extern crate gtk;
//! use gtk::prelude::*;
//! use gtk::{ButtonsType, DialogFlags, MessageType, MessageDialog, Window};
//!
//! fn main() {
//!     if gtk::init().is_err() {
//!         println!("Failed to initialize GTK.");
//!         return;
//!     }
//!     MessageDialog::new(None::<&Window>,
//!                        DialogFlags::empty(),
//!                        MessageType::Info,
//!                        ButtonsType::Ok,
//!                        "Hello World")
//!         .run();
//! }
//! ```
//!
//! # Initialization
//!
//! GTK+ needs to be initialized before use by calling [`init`](fn.init.html).
//! You only need to do it once and there is no 'finalize'.
//!
//! # The main loop
//!
//! In a typical GTK+ application you set up the UI, assign signal handlers
//! and run the main event loop:
//!
//! ```no_run
//! # extern crate gtk;
//! # use gtk::prelude::*;
//! # use gtk::{Window, WindowType};
//! fn main() {
//!     gtk::init().unwrap();
//!     // Create the main window.
//!     let window = Window::new(WindowType::Toplevel);
//!     // UI initialization.
//!     // ...
//!     // Don't forget to make all widgets visible.
//!     window.show_all();
//!     // Handle closing of the window.
//!     window.connect_delete_event(|_, _| {
//!         // Stop the main loop.
//!         gtk::main_quit();
//!         // Let the default handler destroy the window.
//!         Inhibit(false)
//!     });
//!     // Run the main loop.
//!     gtk::main();
//! }
//! ```
//!
//! # Threads
//!
//! GTK+ is not thread-safe. Accoringly, none of this crate's structs implement
//! `Send` or `Sync`.
//!
//! The thread where `init` was called is considered the main thread. OS X has
//! its own notion of the main thread and `init` must be called on that thread.
//! After successful initialization, calling any `gtk` or `gdk` functions
//! (including `init`) from other threads will `panic`.
//!
//! Any thread can schedule a closure to be run by the main loop on the main
//! thread via [`glib::idle_add`](../glib/source/fn.idle_add.html) or
//! [`glib::timeout_add`](../glib/source/fn.timeout_add.html). This crate has
//! versions of those functions without the `Send` bound, which may only be
//! called from the main thread: [`idle_add`](fn.idle_add.html),
//! [`timeout_add`](fn.timeout_add.html).
//!
//! # Panics
//!
//! This and the `gdk` crate have some run-time safety and contract checks:
//!
//! - Any constructor or free function will panic if called before `init` or on
//! a non-main thread.
//!
//! - Any `&str` or `&Path` parameter with an interior null (`\0`) character will
//! cause a panic.
//!
//! - Some functions will panic if supplied out-of-range integer parameters. All
//! such cases will be documented individually but they're not yet.
//!
//! **A panic in a closure will abort the process.**
//!
//! # Crate features
//!
//! ## Library versions
//!
//! By default this crate provides only GTK+ 3.4 APIs. You can access more
//! modern APIs by selecting one of the following features: `3.6`, `3.8`,
//! `3.10`, `3.12`, `3.14`, `3.16`.
//!
//! `Cargo.toml` example:
//!
//! ```toml
//! [dependencies.gtk]
//! version = "0.x.y"
//! features = ["3.16"]
//! ```
//!
//! **Take care when choosing the version to target: some of your users might
//! not have easy access to the latest ones.** The higher the version, the fewer
//! users will have it installed.
//!
//! ## Lgpl-docs
//!
//! The Gtk-rs crates come with API docs missing because of licensing
//! incompatibilty. You can embed those docs locally via the `embed-lgpl-docs`
//! feature, e.g.
//!
//! ```shell
//! > cargo doc --features embed-lgpl-docs
//! ```
//!
//! Its counterpart `purge-lgpl-docs` removes those docs regardless of edits.
//!
//! These features **rewrite the crate sources** so it's sufficient to enable
//! them once. **Omitting them in the following cargo invocations will not undo
//! their effects!**

extern crate libc;

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
#[macro_use]
extern crate glib;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate cairo;
extern crate pango;

pub use glib::{
    Cast,
    Continue,
    Error,
    IsA,
    Object,
    StaticType,
    ToValue,
    Type,
    TypedValue,
    Value,
};

pub use ffi::GtkAccelFlags as AccelFlags;
pub use ffi::GtkAlign as Align;
pub use ffi::GtkArrowPlacement as ArrowPlacement;
pub use ffi::GtkArrowType as ArrowType;
pub use ffi::GtkAttachOptions as AttachOptions;
pub use ffi::GtkBaselinePosition as BaselinePosition;
pub use ffi::GtkBorderStyle as BorderStyle;
pub use ffi::GtkBuilderError as BuilderError;
pub use ffi::GtkButtonBoxStyle as ButtonBoxStyle;
pub use ffi::GtkButtonsType as ButtonsType;
pub use ffi::GtkCalendarDisplayOptions as CalendarDisplayOptions;
pub use ffi::GtkCellRendererState as CellRendererState;
pub use ffi::GtkCornerType as CornerType;
pub use ffi::GtkDeleteType as DeleteType;
pub use ffi::GtkDestDefaults as DestDefaults;
pub use ffi::GtkDialogFlags as DialogFlags;
pub use ffi::GtkDirectionType as DirectionType;
pub use ffi::GtkDragResult as DragResult;
pub use ffi::GtkEntryIconPosition as EntryIconPosition;
pub use ffi::GtkEventSequenceState as EventSequenceState;
pub use ffi::GtkExpanderStyle as ExpanderStyle;
pub use ffi::GtkFileChooserAction as FileChooserAction;
pub use ffi::GtkFileFilterFlags as FileFilterFlags;
pub use ffi::GtkIMPreeditStyle as IMPreeditStyle;
pub use ffi::GtkIMStatusStyle as IMStatusStyle;
pub use ffi::GtkIconSize as IconSize;
pub use ffi::GtkIconViewDropPosition as IconViewDropPosition;
pub use ffi::GtkImageType as ImageType;
pub use ffi::GtkInputHints as InputHints;
pub use ffi::GtkInputPurpose as InputPurpose;
pub use ffi::GtkJunctionSides as JunctionSides;
pub use ffi::GtkJustification as Justification;
pub use ffi::GtkLevelBarMode as LevelBarMode;
pub use ffi::GtkLicense as License;
pub use ffi::GtkMessageType as MessageType;
pub use ffi::GtkMovementStep as MovementStep;
pub use ffi::GtkNumberUpLayout as NumberUpLayout;
pub use ffi::GtkOrientation as Orientation;
pub use ffi::GtkPackType as PackType;
pub use ffi::GtkPageOrientation as PageOrientation;
pub use ffi::GtkPageSet as PageSet;
pub use ffi::GtkPathPriorityType as PathPriorityType;
pub use ffi::GtkPathType as PathType;
pub use ffi::GtkPlacesOpenFlags as PlacesOpenFlags;
pub use ffi::GtkPolicyType as PolicyType;
pub use ffi::GtkPositionType as PositionType;
pub use ffi::GtkPrintDuplex as PrintDuplex;
pub use ffi::GtkPrintPages as PrintPages;
pub use ffi::GtkPrintQuality as PrintQuality;
pub use ffi::GtkPropagationPhase as PropagationPhase;
pub use ffi::GtkRecentFilterFlags as RecentFilterFlags;
pub use ffi::GtkRecentSortType as RecentSortType;
pub use ffi::GtkRegionFlags as RegionFlags;
pub use ffi::GtkReliefStyle as ReliefStyle;
pub use ffi::GtkResizeMode as ResizeMode;
pub use ffi::GtkResponseType as ResponseType;
pub use ffi::GtkRevealerTransitionType as RevealerTransitionType;
pub use ffi::GtkScrollStep as ScrollStep;
pub use ffi::GtkScrollType as ScrollType;
pub use ffi::GtkScrollablePolicy as ScrollablePolicy;
pub use ffi::GtkSelectionMode as SelectionMode;
pub use ffi::GtkSensitivityType as SensitivityType;
pub use ffi::GtkShadowType as ShadowType;
pub use ffi::GtkSizeGroupMode as SizeGroupMode;
pub use ffi::GtkSizeRequestMode as SizeRequestMode;
pub use ffi::GtkSortType as SortType;
pub use ffi::GtkSpinButtonUpdatePolicy as SpinButtonUpdatePolicy;
pub use ffi::GtkSpinType as SpinType;
pub use ffi::GtkStackTransitionType as StackTransitionType;
pub use ffi::GtkStateFlags as StateFlags;
pub use ffi::GtkStateType as StateType;
pub use ffi::GtkTextDirection as TextDirection;
pub use ffi::GtkTextSearchFlags as TextSearchFlags;
pub use ffi::GtkTextWindowType as TextWindowType;
pub use ffi::GtkToolPaletteDragTargets as ToolPaletteDragTargets;
pub use ffi::GtkToolbarStyle as ToolbarStyle;
pub use ffi::GtkTreeModelFlags as TreeModelFlags;
pub use ffi::GtkTreeViewColumnSizing as TreeViewColumnSizing;
pub use ffi::GtkTreeViewDropPosition as TreeViewDropPosition;
pub use ffi::GtkTreeViewGridLines as TreeViewGridLines;
pub use ffi::GtkUnit as Unit;
pub use ffi::GtkWidgetHelpType as WidgetHelpType;
pub use ffi::GtkWindowPosition as WindowPosition;
pub use ffi::GtkWindowType as WindowType;
pub use ffi::GtkWrapMode as WrapMode;

pub const DIALOG_MODAL: DialogFlags = ffi::GTK_DIALOG_MODAL;

pub const STYLE_PROVIDER_PRIORITY_FALLBACK: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
pub const STYLE_PROVIDER_PRIORITY_THEME: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_THEME;
pub const STYLE_PROVIDER_PRIORITY_SETTINGS: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_SETTINGS;
pub const STYLE_PROVIDER_PRIORITY_APPLICATION: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
pub const STYLE_PROVIDER_PRIORITY_USER: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;

#[macro_use]
mod rt;

mod auto;

mod app_chooser;
mod builder;
mod color_button;
mod color_chooser;
mod dialog;
mod entry_buffer;
mod file_chooser_dialog;
mod list_store;
mod message_dialog;
mod notebook;
mod recent_chooser_dialog;
mod recent_data;
mod recent_info;
mod rectangle;
mod requisition;
mod signal;
#[cfg(target_os = "linux")]
mod socket;
mod text_attributes;
mod text_buffer;
mod text_iter;
mod text_view;
mod tree_model;
mod tree_sortable;
mod tree_path;
mod tree_store;
mod tree_view;
mod widget;

pub mod prelude;

pub use auto::*;
pub use rt::*;
pub use signal::*;

pub use rectangle::Rectangle as Allocation;
pub use app_chooser::AppChooser;
pub use builder::{Builder, Buildable};
pub use color_chooser::ColorChooser;
pub use entry_buffer::EntryBuffer;
pub use recent_data::RecentData;
pub use recent_info::RecentInfo;
pub use rectangle::Rectangle;
pub use requisition::Requisition;
#[cfg(target_os = "linux")]
pub use socket::Socket;
pub use text_attributes::TextAttributes;
pub use tree_sortable::SortColumn;
<commit_msg>Reexport ApplicationInhibitFlags<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # GTK+ 3 bindings
//!
//! This library contains safe Rust bindings for [GTK+ 3](http://www.gtk.org), a
//! multi-platform GUI toolkit. It's a part of [Gtk-rs](http://gtk-rs.org/).
//!
//! The library is a work in progress: expect missing bindings and breaking
//! changes. A steadily increasing share of the code is machine-generated from
//! GObject introspection metadata. The API docs were converted from the
//! upstream ones so until they've all been reviewed there will be incongruities
//! with actual Rust APIs.
//!
//! See also:
//!
//! - [Gtk-rs documentation overview](http://gtk-rs.org/docs/)
//!
//! - [General GLib family types and object system overview](../glib/index.html)
//!
//! - [GTK+ documentation](http://www.gtk.org/documentation.php)
//!
//! # Hello World
//!
//! ```no_run
//! extern crate gtk;
//! use gtk::prelude::*;
//! use gtk::{ButtonsType, DialogFlags, MessageType, MessageDialog, Window};
//!
//! fn main() {
//!     if gtk::init().is_err() {
//!         println!("Failed to initialize GTK.");
//!         return;
//!     }
//!     MessageDialog::new(None::<&Window>,
//!                        DialogFlags::empty(),
//!                        MessageType::Info,
//!                        ButtonsType::Ok,
//!                        "Hello World")
//!         .run();
//! }
//! ```
//!
//! # Initialization
//!
//! GTK+ needs to be initialized before use by calling [`init`](fn.init.html).
//! You only need to do it once and there is no 'finalize'.
//!
//! # The main loop
//!
//! In a typical GTK+ application you set up the UI, assign signal handlers
//! and run the main event loop:
//!
//! ```no_run
//! # extern crate gtk;
//! # use gtk::prelude::*;
//! # use gtk::{Window, WindowType};
//! fn main() {
//!     gtk::init().unwrap();
//!     // Create the main window.
//!     let window = Window::new(WindowType::Toplevel);
//!     // UI initialization.
//!     // ...
//!     // Don't forget to make all widgets visible.
//!     window.show_all();
//!     // Handle closing of the window.
//!     window.connect_delete_event(|_, _| {
//!         // Stop the main loop.
//!         gtk::main_quit();
//!         // Let the default handler destroy the window.
//!         Inhibit(false)
//!     });
//!     // Run the main loop.
//!     gtk::main();
//! }
//! ```
//!
//! # Threads
//!
//! GTK+ is not thread-safe. Accoringly, none of this crate's structs implement
//! `Send` or `Sync`.
//!
//! The thread where `init` was called is considered the main thread. OS X has
//! its own notion of the main thread and `init` must be called on that thread.
//! After successful initialization, calling any `gtk` or `gdk` functions
//! (including `init`) from other threads will `panic`.
//!
//! Any thread can schedule a closure to be run by the main loop on the main
//! thread via [`glib::idle_add`](../glib/source/fn.idle_add.html) or
//! [`glib::timeout_add`](../glib/source/fn.timeout_add.html). This crate has
//! versions of those functions without the `Send` bound, which may only be
//! called from the main thread: [`idle_add`](fn.idle_add.html),
//! [`timeout_add`](fn.timeout_add.html).
//!
//! # Panics
//!
//! This and the `gdk` crate have some run-time safety and contract checks:
//!
//! - Any constructor or free function will panic if called before `init` or on
//! a non-main thread.
//!
//! - Any `&str` or `&Path` parameter with an interior null (`\0`) character will
//! cause a panic.
//!
//! - Some functions will panic if supplied out-of-range integer parameters. All
//! such cases will be documented individually but they're not yet.
//!
//! **A panic in a closure will abort the process.**
//!
//! # Crate features
//!
//! ## Library versions
//!
//! By default this crate provides only GTK+ 3.4 APIs. You can access more
//! modern APIs by selecting one of the following features: `3.6`, `3.8`,
//! `3.10`, `3.12`, `3.14`, `3.16`.
//!
//! `Cargo.toml` example:
//!
//! ```toml
//! [dependencies.gtk]
//! version = "0.x.y"
//! features = ["3.16"]
//! ```
//!
//! **Take care when choosing the version to target: some of your users might
//! not have easy access to the latest ones.** The higher the version, the fewer
//! users will have it installed.
//!
//! ## Lgpl-docs
//!
//! The Gtk-rs crates come with API docs missing because of licensing
//! incompatibilty. You can embed those docs locally via the `embed-lgpl-docs`
//! feature, e.g.
//!
//! ```shell
//! > cargo doc --features embed-lgpl-docs
//! ```
//!
//! Its counterpart `purge-lgpl-docs` removes those docs regardless of edits.
//!
//! These features **rewrite the crate sources** so it's sufficient to enable
//! them once. **Omitting them in the following cargo invocations will not undo
//! their effects!**

extern crate libc;

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
#[macro_use]
extern crate glib;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate cairo;
extern crate pango;

pub use glib::{
    Cast,
    Continue,
    Error,
    IsA,
    Object,
    StaticType,
    ToValue,
    Type,
    TypedValue,
    Value,
};

pub use ffi::GtkAccelFlags as AccelFlags;
pub use ffi::GtkAlign as Align;
pub use ffi::GtkApplicationInhibitFlags as ApplicationInhibitFlags;
pub use ffi::GtkArrowPlacement as ArrowPlacement;
pub use ffi::GtkArrowType as ArrowType;
pub use ffi::GtkAttachOptions as AttachOptions;
pub use ffi::GtkBaselinePosition as BaselinePosition;
pub use ffi::GtkBorderStyle as BorderStyle;
pub use ffi::GtkBuilderError as BuilderError;
pub use ffi::GtkButtonBoxStyle as ButtonBoxStyle;
pub use ffi::GtkButtonsType as ButtonsType;
pub use ffi::GtkCalendarDisplayOptions as CalendarDisplayOptions;
pub use ffi::GtkCellRendererState as CellRendererState;
pub use ffi::GtkCornerType as CornerType;
pub use ffi::GtkDeleteType as DeleteType;
pub use ffi::GtkDestDefaults as DestDefaults;
pub use ffi::GtkDialogFlags as DialogFlags;
pub use ffi::GtkDirectionType as DirectionType;
pub use ffi::GtkDragResult as DragResult;
pub use ffi::GtkEntryIconPosition as EntryIconPosition;
pub use ffi::GtkEventSequenceState as EventSequenceState;
pub use ffi::GtkExpanderStyle as ExpanderStyle;
pub use ffi::GtkFileChooserAction as FileChooserAction;
pub use ffi::GtkFileFilterFlags as FileFilterFlags;
pub use ffi::GtkIMPreeditStyle as IMPreeditStyle;
pub use ffi::GtkIMStatusStyle as IMStatusStyle;
pub use ffi::GtkIconSize as IconSize;
pub use ffi::GtkIconViewDropPosition as IconViewDropPosition;
pub use ffi::GtkImageType as ImageType;
pub use ffi::GtkInputHints as InputHints;
pub use ffi::GtkInputPurpose as InputPurpose;
pub use ffi::GtkJunctionSides as JunctionSides;
pub use ffi::GtkJustification as Justification;
pub use ffi::GtkLevelBarMode as LevelBarMode;
pub use ffi::GtkLicense as License;
pub use ffi::GtkMessageType as MessageType;
pub use ffi::GtkMovementStep as MovementStep;
pub use ffi::GtkNumberUpLayout as NumberUpLayout;
pub use ffi::GtkOrientation as Orientation;
pub use ffi::GtkPackType as PackType;
pub use ffi::GtkPageOrientation as PageOrientation;
pub use ffi::GtkPageSet as PageSet;
pub use ffi::GtkPathPriorityType as PathPriorityType;
pub use ffi::GtkPathType as PathType;
pub use ffi::GtkPlacesOpenFlags as PlacesOpenFlags;
pub use ffi::GtkPolicyType as PolicyType;
pub use ffi::GtkPositionType as PositionType;
pub use ffi::GtkPrintDuplex as PrintDuplex;
pub use ffi::GtkPrintPages as PrintPages;
pub use ffi::GtkPrintQuality as PrintQuality;
pub use ffi::GtkPropagationPhase as PropagationPhase;
pub use ffi::GtkRecentFilterFlags as RecentFilterFlags;
pub use ffi::GtkRecentSortType as RecentSortType;
pub use ffi::GtkRegionFlags as RegionFlags;
pub use ffi::GtkReliefStyle as ReliefStyle;
pub use ffi::GtkResizeMode as ResizeMode;
pub use ffi::GtkResponseType as ResponseType;
pub use ffi::GtkRevealerTransitionType as RevealerTransitionType;
pub use ffi::GtkScrollStep as ScrollStep;
pub use ffi::GtkScrollType as ScrollType;
pub use ffi::GtkScrollablePolicy as ScrollablePolicy;
pub use ffi::GtkSelectionMode as SelectionMode;
pub use ffi::GtkSensitivityType as SensitivityType;
pub use ffi::GtkShadowType as ShadowType;
pub use ffi::GtkSizeGroupMode as SizeGroupMode;
pub use ffi::GtkSizeRequestMode as SizeRequestMode;
pub use ffi::GtkSortType as SortType;
pub use ffi::GtkSpinButtonUpdatePolicy as SpinButtonUpdatePolicy;
pub use ffi::GtkSpinType as SpinType;
pub use ffi::GtkStackTransitionType as StackTransitionType;
pub use ffi::GtkStateFlags as StateFlags;
pub use ffi::GtkStateType as StateType;
pub use ffi::GtkTextDirection as TextDirection;
pub use ffi::GtkTextSearchFlags as TextSearchFlags;
pub use ffi::GtkTextWindowType as TextWindowType;
pub use ffi::GtkToolPaletteDragTargets as ToolPaletteDragTargets;
pub use ffi::GtkToolbarStyle as ToolbarStyle;
pub use ffi::GtkTreeModelFlags as TreeModelFlags;
pub use ffi::GtkTreeViewColumnSizing as TreeViewColumnSizing;
pub use ffi::GtkTreeViewDropPosition as TreeViewDropPosition;
pub use ffi::GtkTreeViewGridLines as TreeViewGridLines;
pub use ffi::GtkUnit as Unit;
pub use ffi::GtkWidgetHelpType as WidgetHelpType;
pub use ffi::GtkWindowPosition as WindowPosition;
pub use ffi::GtkWindowType as WindowType;
pub use ffi::GtkWrapMode as WrapMode;

pub const DIALOG_MODAL: DialogFlags = ffi::GTK_DIALOG_MODAL;

pub const STYLE_PROVIDER_PRIORITY_FALLBACK: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
pub const STYLE_PROVIDER_PRIORITY_THEME: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_THEME;
pub const STYLE_PROVIDER_PRIORITY_SETTINGS: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_SETTINGS;
pub const STYLE_PROVIDER_PRIORITY_APPLICATION: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
pub const STYLE_PROVIDER_PRIORITY_USER: i32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;

#[macro_use]
mod rt;

mod auto;

mod app_chooser;
mod builder;
mod color_button;
mod color_chooser;
mod dialog;
mod entry_buffer;
mod file_chooser_dialog;
mod list_store;
mod message_dialog;
mod notebook;
mod recent_chooser_dialog;
mod recent_data;
mod recent_info;
mod rectangle;
mod requisition;
mod signal;
#[cfg(target_os = "linux")]
mod socket;
mod text_attributes;
mod text_buffer;
mod text_iter;
mod text_view;
mod tree_model;
mod tree_sortable;
mod tree_path;
mod tree_store;
mod tree_view;
mod widget;

pub mod prelude;

pub use auto::*;
pub use rt::*;
pub use signal::*;

pub use rectangle::Rectangle as Allocation;
pub use app_chooser::AppChooser;
pub use builder::{Builder, Buildable};
pub use color_chooser::ColorChooser;
pub use entry_buffer::EntryBuffer;
pub use recent_data::RecentData;
pub use recent_info::RecentInfo;
pub use rectangle::Rectangle;
pub use requisition::Requisition;
#[cfg(target_os = "linux")]
pub use socket::Socket;
pub use text_attributes::TextAttributes;
pub use tree_sortable::SortColumn;
<|endoftext|>


<commit_before>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "solaris",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
}
<commit_msg>Implement get_physical() by parsing /proc/cpuinfo<commit_after>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::collections::HashMap;
/// Returns the number of physical cores of the current machine.
/// If not possible on the particular architecture returns same as get() which
/// is the logical CPUs.
pub fn get_physical() -> usize {
    let file = match File::open("/proc/cpuinfo") {
      Ok(val) => val,
      Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut map = HashMap::new();
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
          continue
        }
        if parts[0] == "core id" {
          map.insert(parts[1].to_string(), true);
        }
    }
    let count = map.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "solaris",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
}
<|endoftext|>


<commit_before>//! SIMD support
//!
//! This crate provides the fundamentals of supporting SIMD in Rust. This crate
//! should compile on all platforms and provide `simd` and `vendor` modules at
//! the top-level. The `simd` module contains *portable vector types* which
//! should work across all platforms and be implemented in the most efficient
//! manner possible for the platform at hand. The `vendor` module contains
//! vendor intrinsics that operate over these SIMD types, typically
//! corresponding to a particular CPU instruction
//!
//! ```rust
//! extern crate stdsimd;
//! use stdsimd::simd::u32x4;
//!
//! fn main() {
//!     let a = u32x4::new(1, 2, 3, 4);
//!     let b = u32x4::splat(10);
//!     assert_eq!(a + b, u32x4::new(11, 12, 13, 14));
//! }
//! ```
//!
//! > **Note**: This crate is *nightly only* at the moment, and requires a
//! > nightly rust toolchain to compile.
//!
//! This documentation is only for one particular architecture, you can find
//! others at:
//!
//! * [i686](https://rust-lang-nursery.github.io/stdsimd/i686/stdsimd/)
//! * [`x86_64`](https://rust-lang-nursery.github.io/stdsimd/x86_64/stdsimd/)
//! * [arm](https://rust-lang-nursery.github.io/stdsimd/arm/stdsimd/)
//! * [aarch64](https://rust-lang-nursery.github.io/stdsimd/aarch64/stdsimd/)
//!
//! ## Portability
//!
//! The `simd` module and its types should be portable to all platforms. The
//! runtime characteristics of these types may vary per platform and per CPU
//! feature enabled, but they should always have the most optimized
//! implementation for the target at hand.
//!
//! The `vendor` module provides no portability guarantees. The `vendor` module
//! is per CPU architecture currently and provides intrinsics corresponding to
//! functions for that particular CPU architecture. Note that the functions
//! provided in this module are intended to correspond to CPU instructions and
//! have no runtime support for whether you CPU actually supports the
//! instruction.
//!
//! CPU target feature detection is done via the `cfg_feature_enabled!` macro
//! at runtime. This macro will detect at runtime whether the specified feature
//! is available or not, returning true or false depending on the current CPU.
//!
//! ```
//! #![feature(cfg_target_feature)]
//!
//! #[macro_use]
//! extern crate stdsimd;
//!
//! fn main() {
//!     if cfg_feature_enabled!("avx2") {
//!         println!("avx2 intrinsics will work");
//!     } else {
//!         println!("avx2 intrinsics will not work");
//!         // undefined behavior: may generate a `SIGILL`.
//!     }
//! }
//! ```
//!
//! After verifying that a specified feature is available, use `target_feature`
//! to enable a given feature and use the desired intrinsic.
//!
//! ```ignore
//! # #![feature(cfg_target_feature)]
//! # #![feature(target_feature)]
//! # #[macro_use]
//! # extern crate stdsimd;
//! # fn main() {
//! #     if cfg_feature_enabled!("avx2") {
//! // avx2 specific code may be used in this function
//! #[target_feature = "+avx2"]
//! fn and_256() {
//!     // avx2 feature specific intrinsics will work here!
//!     use stdsimd::vendor::{__m256i, _mm256_and_si256};
//!
//!     let a = __m256i::splat(5);
//!     let b = __m256i::splat(3);
//!
//!     let got = unsafe { _mm256_and_si256(a, b) };
//!
//!     assert_eq!(got, __m256i::splat(1));
//! }
//! #         and_256();
//! #     }
//! # }
//! ```
//!
//! # Status
//!
//! This crate is intended for eventual inclusion into the standard library,
//! but some work and experimentation is needed to get there! First and
//! foremost you can help out by kicking the tires on this crate and seeing if
//! it works for your use case! Next up you can help us fill out the [vendor
//! intrinsics][vendor] to ensure that we've got all the SIMD support
//! necessary.
//!
//! The language support and status of SIMD is also still a little up in the
//! air right now, you may be interested in a few issues along these lines:
//!
//! * [Overal tracking issue for SIMD support]
//!   (https://github.com/rust-lang/rust/issues/27731)
//! * [`cfg_target_feature` tracking issue]
//!   (https://github.com/rust-lang/rust/issues/29717)
//! * [SIMD types currently not sound]
//!   (https://github.com/rust-lang/rust/issues/44367)
//! * [`#[target_feature]` improvements]
//!   (https://github.com/rust-lang/rust/issues/44839)
//!
//! [vendor]: https://github.com/rust-lang-nursery/stdsimd/issues/40

#![cfg_attr(feature = "strict", deny(warnings))]
#![allow(dead_code)]
#![allow(unused_features)]
#![feature(const_fn, link_llvm_intrinsics, platform_intrinsics, repr_simd,
           simd_ffi, target_feature, cfg_target_feature, i128_type, asm,
           const_atomic_usize_new, stmt_expr_attributes)]
#![cfg_attr(test, feature(proc_macro, test, repr_align, attr_literals))]
#![cfg_attr(feature = "cargo-clippy",
            allow(inline_always, too_many_arguments, cast_sign_loss,
                  cast_lossless, cast_possible_wrap,
                  cast_possible_truncation, cast_precision_loss,
                  shadow_reuse, cyclomatic_complexity, similar_names,
                  doc_markdown, many_single_char_names))]
#![no_std]

#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;

#[cfg(test)]
extern crate stdsimd_test;

#[cfg(test)]
extern crate test;

/// Platform independent SIMD vector types and operations.
pub mod simd {
    pub use v128::*;
    pub use v256::*;
    pub use v512::*;
    pub use v64::*;
}

/// Platform dependent vendor intrinsics.
pub mod vendor {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    pub use x86::*;

    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    pub use arm::*;

    #[cfg(target_arch = "aarch64")]
    pub use aarch64::*;

    pub use nvptx::*;

    #[cfg(any(
        // x86/x86_64:
        any(target_arch = "x86", target_arch = "x86_64"),
        // linux + std + (arm|aarch64):
        all(target_os = "linux",
            feature = "std",
            any(target_arch = "arm", target_arch = "aarch64"))
    ))]
    pub use runtime::{__unstable_detect_feature, __Feature};
}

#[cfg(any(
    // x86/x86_64:
    any(target_arch = "x86", target_arch = "x86_64"),
    // linux + std + (arm|aarch64):
    all(target_os = "linux",
        feature = "std",
        any(target_arch = "arm", target_arch = "aarch64"))
))]
#[macro_use]
mod runtime;

#[macro_use]
mod macros;
mod simd_llvm;
mod v128;
mod v256;
mod v512;
mod v64;

/// 32-bit wide vector tpyes
mod v32 {
    use simd_llvm::*;

    define_ty! { i16x2, i16, i16 }
    define_impl! { i16x2, i16, 2, i16x2, x0, x1 }
    define_ty! { u16x2, u16, u16 }
    define_impl! { u16x2, u16, 2, i16x2, x0, x1 }

    define_ty! { i8x4, i8, i8, i8, i8 }
    define_impl! { i8x4, i8, 4, i8x4, x0, x1, x2, x3 }
    define_ty! { u8x4, u8, u8, u8, u8 }
    define_impl! { u8x4, u8, 4, i8x4, x0, x1, x2, x3 }

    define_casts!(
        (i16x2, i64x2, as_i64x2),
        (u16x2, i64x2, as_i64x2),
        (i8x4, i32x4, as_i32x4),
        (u8x4, i32x4, as_i32x4)
    );
}

/// 16-bit wide vector tpyes
mod v16 {
    use simd_llvm::*;

    define_ty! { i8x2, i8, i8 }
    define_impl! { i8x2, i8, 2, i8x2, x0, x1 }
    define_ty! { u8x2, u8, u8 }
    define_impl! { u8x2, u8, 2, i8x2, x0, x1 }

    define_casts!((i8x2, i64x2, as_i64x2), (u8x2, i64x2, as_i64x2));
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86;

#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
mod arm;
#[cfg(target_arch = "aarch64")]
mod aarch64;

mod nvptx;
<commit_msg>[nvptx] enable nvptx only when all other targets are disabled (#208)<commit_after>//! SIMD support
//!
//! This crate provides the fundamentals of supporting SIMD in Rust. This crate
//! should compile on all platforms and provide `simd` and `vendor` modules at
//! the top-level. The `simd` module contains *portable vector types* which
//! should work across all platforms and be implemented in the most efficient
//! manner possible for the platform at hand. The `vendor` module contains
//! vendor intrinsics that operate over these SIMD types, typically
//! corresponding to a particular CPU instruction
//!
//! ```rust
//! extern crate stdsimd;
//! use stdsimd::simd::u32x4;
//!
//! fn main() {
//!     let a = u32x4::new(1, 2, 3, 4);
//!     let b = u32x4::splat(10);
//!     assert_eq!(a + b, u32x4::new(11, 12, 13, 14));
//! }
//! ```
//!
//! > **Note**: This crate is *nightly only* at the moment, and requires a
//! > nightly rust toolchain to compile.
//!
//! This documentation is only for one particular architecture, you can find
//! others at:
//!
//! * [i686](https://rust-lang-nursery.github.io/stdsimd/i686/stdsimd/)
//! * [`x86_64`](https://rust-lang-nursery.github.io/stdsimd/x86_64/stdsimd/)
//! * [arm](https://rust-lang-nursery.github.io/stdsimd/arm/stdsimd/)
//! * [aarch64](https://rust-lang-nursery.github.io/stdsimd/aarch64/stdsimd/)
//!
//! ## Portability
//!
//! The `simd` module and its types should be portable to all platforms. The
//! runtime characteristics of these types may vary per platform and per CPU
//! feature enabled, but they should always have the most optimized
//! implementation for the target at hand.
//!
//! The `vendor` module provides no portability guarantees. The `vendor` module
//! is per CPU architecture currently and provides intrinsics corresponding to
//! functions for that particular CPU architecture. Note that the functions
//! provided in this module are intended to correspond to CPU instructions and
//! have no runtime support for whether you CPU actually supports the
//! instruction.
//!
//! CPU target feature detection is done via the `cfg_feature_enabled!` macro
//! at runtime. This macro will detect at runtime whether the specified feature
//! is available or not, returning true or false depending on the current CPU.
//!
//! ```
//! #![feature(cfg_target_feature)]
//!
//! #[macro_use]
//! extern crate stdsimd;
//!
//! fn main() {
//!     if cfg_feature_enabled!("avx2") {
//!         println!("avx2 intrinsics will work");
//!     } else {
//!         println!("avx2 intrinsics will not work");
//!         // undefined behavior: may generate a `SIGILL`.
//!     }
//! }
//! ```
//!
//! After verifying that a specified feature is available, use `target_feature`
//! to enable a given feature and use the desired intrinsic.
//!
//! ```ignore
//! # #![feature(cfg_target_feature)]
//! # #![feature(target_feature)]
//! # #[macro_use]
//! # extern crate stdsimd;
//! # fn main() {
//! #     if cfg_feature_enabled!("avx2") {
//! // avx2 specific code may be used in this function
//! #[target_feature = "+avx2"]
//! fn and_256() {
//!     // avx2 feature specific intrinsics will work here!
//!     use stdsimd::vendor::{__m256i, _mm256_and_si256};
//!
//!     let a = __m256i::splat(5);
//!     let b = __m256i::splat(3);
//!
//!     let got = unsafe { _mm256_and_si256(a, b) };
//!
//!     assert_eq!(got, __m256i::splat(1));
//! }
//! #         and_256();
//! #     }
//! # }
//! ```
//!
//! # Status
//!
//! This crate is intended for eventual inclusion into the standard library,
//! but some work and experimentation is needed to get there! First and
//! foremost you can help out by kicking the tires on this crate and seeing if
//! it works for your use case! Next up you can help us fill out the [vendor
//! intrinsics][vendor] to ensure that we've got all the SIMD support
//! necessary.
//!
//! The language support and status of SIMD is also still a little up in the
//! air right now, you may be interested in a few issues along these lines:
//!
//! * [Overal tracking issue for SIMD support]
//!   (https://github.com/rust-lang/rust/issues/27731)
//! * [`cfg_target_feature` tracking issue]
//!   (https://github.com/rust-lang/rust/issues/29717)
//! * [SIMD types currently not sound]
//!   (https://github.com/rust-lang/rust/issues/44367)
//! * [`#[target_feature]` improvements]
//!   (https://github.com/rust-lang/rust/issues/44839)
//!
//! [vendor]: https://github.com/rust-lang-nursery/stdsimd/issues/40

#![cfg_attr(feature = "strict", deny(warnings))]
#![allow(dead_code)]
#![allow(unused_features)]
#![feature(const_fn, link_llvm_intrinsics, platform_intrinsics, repr_simd,
           simd_ffi, target_feature, cfg_target_feature, i128_type, asm,
           const_atomic_usize_new, stmt_expr_attributes)]
#![cfg_attr(test, feature(proc_macro, test, repr_align, attr_literals))]
#![cfg_attr(feature = "cargo-clippy",
            allow(inline_always, too_many_arguments, cast_sign_loss,
                  cast_lossless, cast_possible_wrap,
                  cast_possible_truncation, cast_precision_loss,
                  shadow_reuse, cyclomatic_complexity, similar_names,
                  doc_markdown, many_single_char_names))]
#![no_std]

#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;

#[cfg(test)]
extern crate stdsimd_test;

#[cfg(test)]
extern crate test;

/// Platform independent SIMD vector types and operations.
pub mod simd {
    pub use v128::*;
    pub use v256::*;
    pub use v512::*;
    pub use v64::*;
}

/// Platform dependent vendor intrinsics.
pub mod vendor {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    pub use x86::*;

    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    pub use arm::*;

    #[cfg(target_arch = "aarch64")]
    pub use aarch64::*;

    // FIXME: rust does not expose the nvptx and nvptx64 targets yet
    #[cfg(not(any(target_arch = "x86", target_arch = "x86_64",
                  target_arch = "arm", target_arch = "aarch64")))]
    pub use nvptx::*;

    #[cfg(any(
        // x86/x86_64:
        any(target_arch = "x86", target_arch = "x86_64"),
        // linux + std + (arm|aarch64):
        all(target_os = "linux",
            feature = "std",
            any(target_arch = "arm", target_arch = "aarch64"))
    ))]
    pub use runtime::{__unstable_detect_feature, __Feature};
}

#[cfg(any(
    // x86/x86_64:
    any(target_arch = "x86", target_arch = "x86_64"),
    // linux + std + (arm|aarch64):
    all(target_os = "linux",
        feature = "std",
        any(target_arch = "arm", target_arch = "aarch64"))
))]
#[macro_use]
mod runtime;

#[macro_use]
mod macros;
mod simd_llvm;
mod v128;
mod v256;
mod v512;
mod v64;

/// 32-bit wide vector tpyes
mod v32 {
    use simd_llvm::*;

    define_ty! { i16x2, i16, i16 }
    define_impl! { i16x2, i16, 2, i16x2, x0, x1 }
    define_ty! { u16x2, u16, u16 }
    define_impl! { u16x2, u16, 2, i16x2, x0, x1 }

    define_ty! { i8x4, i8, i8, i8, i8 }
    define_impl! { i8x4, i8, 4, i8x4, x0, x1, x2, x3 }
    define_ty! { u8x4, u8, u8, u8, u8 }
    define_impl! { u8x4, u8, 4, i8x4, x0, x1, x2, x3 }

    define_casts!(
        (i16x2, i64x2, as_i64x2),
        (u16x2, i64x2, as_i64x2),
        (i8x4, i32x4, as_i32x4),
        (u8x4, i32x4, as_i32x4)
    );
}

/// 16-bit wide vector tpyes
mod v16 {
    use simd_llvm::*;

    define_ty! { i8x2, i8, i8 }
    define_impl! { i8x2, i8, 2, i8x2, x0, x1 }
    define_ty! { u8x2, u8, u8 }
    define_impl! { u8x2, u8, 2, i8x2, x0, x1 }

    define_casts!((i8x2, i64x2, as_i64x2), (u8x2, i64x2, as_i64x2));
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86;

#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
mod arm;
#[cfg(target_arch = "aarch64")]
mod aarch64;

// FIXME: rust does not expose the nvptx and nvptx64 targets yet
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64",
              target_arch = "arm", target_arch = "aarch64")))]
mod nvptx;
<|endoftext|>