<commit_before>//! Reminisce is a lightweight library intended to be used for detecting and
//! reading from joysticks.
#![feature(into_cow, io)]
#![cfg_attr(feature = "mappings", feature(alloc))]
#![cfg_attr(target_os = "linux", feature(libc, fs_walk))]
extern crate libc;
#[cfg(target_os = "windows")]
#[macro_use] extern crate rustc_bitflags;

#[cfg(feature = "sdl")]
extern crate sdl2;

/// Someday, somehow
#[cfg(all(feature = "emscripten", not(feature = "sdl")))]
pub mod emscripten;

#[cfg(all(feature = "emscripten", not(feature = "sdl")))]
pub use emscripten as native;

#[cfg(all(target_os = "linux", not(feature = "sdl")))]
pub mod linux;

#[cfg(all(target_os = "linux", not(feature = "sdl")))]
pub use linux as native;

#[cfg(all(target_os = "windows", not(feature = "sdl")))]
pub mod windows;

#[cfg(all(target_os = "windows", not(feature = "sdl")))]
pub use windows as native;

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

#[cfg(feature = "sdl")]
pub use sdl as native;

#[cfg(feature = "mappings")]
pub mod mapper;

#[cfg(feature = "mappings")]
pub use mapper::JoystickMapper;
pub use native::{NativeJoystick, scan};

/// The maximum axis value
pub static MAX_AXIS_VALUE:i16 = 32767;
/// The minimum axis value
pub static MIN_AXIS_VALUE:i16 = -32767;

use std::borrow::Cow;
use std::error::Error;
use std::fmt::Debug;
use std::mem::transmute as cast;

#[cfg(feature = "mappings")]
macro_rules! text_enum(
    ($name:ident, $($enumer:ident => $text:expr),+) => (
        impl ::std::fmt::Display for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                write!(fmt, "{}", match *self {
                    $($name::$enumer => $text),+
                })
            }
        }
        impl ::std::str::FromStr for $name {
            type Err = String;
            fn from_str(s: &str) -> Result<$name, String> {
                match s {
                    $($text => Ok($name::$enumer),)+
                    _ => Err(format!("Could not make {} from {}", stringify!($name), s))
                }
            }
        }
    )
);
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A direction on a joystick
///
/// This uses the order that Linux drivers and the HTML5 Gamepad API uses so it should ring a bell
pub enum Axis {
	/// The x direction of the left stick
    ///
    /// This is usually used for horizontal movement in a game
    LeftX,
	/// The y direction of the left stick
    ///
    /// This is usually used for vertical movement in a game
    LeftY,
	/// The x direction of the right stick
    //
    /// This is usually used for looking around in a game
    RightX,
	/// The y direction of the right stick
    //
    /// This is usually used for looking around in a game
    RightY,
	/// How far down the left trigger is pressed
    ///
    /// This is only used as a button on some platforms so don't rely on just this
    TriggerLeft,
	/// How far down the right trigger is pressed
    ///
    /// This is only used as a button on some platforms so don't rely on just this
    TriggerRight
}
#[cfg(feature = "mappings")]
text_enum!(Axis,
    LeftX => "leftx",
    LeftY => "lefty",
    RightX => "rightx",
    RightY => "righty",
    TriggerLeft => "triggerleft",
    TriggerRight => "triggerright"
);

#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A button on a joystick
///
/// This uses the order that Linux drivers and the HTML5 Gamepad API uses so it should be familiar
pub enum Button {
	/// The A button
    ///
    /// This is typically used for jumping
	A,
	/// The B button
    ///
    /// This is typically used for hitting
	B,
	/// The X button
	X,
	/// The Y button
	Y,
	/// The left top shoulder button
    ///
    /// This is usually used in FPS games for throwing a certain kind of grenade
	LeftShoulder,
	/// The right top shoulder button
	RightShoulder,
	/// The left bottom shoulder / trigger button
    ///
    /// This is typically used in FPS games for aiming down the sights in a weapon
	LeftTrigger,
	/// The right bottom shoulder / trigger button
    ///
    /// This is typically used in FPS games for shooting with a weapon
	RightTrigger,
	/// The back / select button
    ///
    /// This is usually used as an alternate pause menu or to open a menu in-game.
	Select,
	/// The start / forward button
    ///
    /// This is usually used to start and pause a game
	Start,
	/// The left stick button
	LeftStick,
	/// The right stick button
	RightStick,
	/// The up button on the directional pad
	DPadUp,
	/// The down button on the directional pad
	DPadDown,
	/// The left button on the directional pad
	DPadLeft,
	/// The right button on the directional pad
	DPadRight
}
#[cfg(feature = "mappings")]
text_enum!(Button,
    A => "a",
    B => "b",
    X => "x",
    Y => "y",
    LeftShoulder => "leftshoulder",
    RightShoulder => "rightshoulder",
    LeftTrigger => "lefttrigger",
    RightTrigger => "righttrigger",
    Select => "select",
    Start => "start",
    LeftStick => "leftstick",
    RightStick => "rightstick",
    DPadUp => "dpadup",
    DPadDown => "dpaddown",
    DPadLeft => "dpadleft",
    DPadRight => "dpadright"
);

#[derive(Copy, Debug, Eq, PartialEq)]
/// An event from a joystick
pub enum Event {
	/// Fired when a button is pressed with the button's index
	ButtonPressed(Button),
	/// Fired when a button is released with the button's index
	ButtonReleased(Button),
	/// Fired when a axis is moved with the axis index and its value,
	/// which is between `MIN_JOYSTICK_VALUE` and `MAX_JOYSTICK_VALUE`
	AxisMoved(Axis, i16)
}
/// Convert a raw event into a Reminisce event
pub trait IntoEvent {
	/// Convert this into a Reminisce event
	fn into_event(self) -> Event;
}

impl IntoEvent for Event {
    /// Convert the event into itself
    ///
    /// The only reason this exists is because windows doesn't have events so the backend has to
    /// make reminisce events directly and pretend that they are the native events.
    fn into_event(self) -> Event {
        self
    }
}

/// A joystick or gamepad
///
/// Each `Joystick` has its own event queue that can be polled repeatedly
/// using the `iter()` method or by calling the `poll()` method repeatedly.
///
/// ``` rust
/// use reminisce::{scan, Axis, Event, Joystick};
/// let mut joysticks = scan();
/// let (mut x, mut y) = (0, 0);
/// for joystick in &mut joysticks {
///     for event in joystick.iter() {
///         match event {
///             Event::AxisMoved(Axis::LeftX, nx) =>
///                 x += nx,
///             Event::AxisMoved(Axis::LeftY, ny) =>
///                 y += ny,
///             _ => ()
///         }
///     }
/// }
/// println!("{}, {}", x, y);
/// ```
pub trait Joystick : Sized {
	/// The version of this joystick that includes the state
    ///
    /// On Linux, this is a wrapper around the joystick, but on Windows,
    /// this is the same stucture because the joystick always includes
    /// state on it.
	type WithState : StatefulJoystick;

    /// The event that this joystick processes
    type NativeEvent: IntoEvent;

    type OpenError: Error + Debug;

	/// Create a new joystick from its index
    ///
    /// If an error occurs, this will return the textual representation of that error.
    ///
    /// ``` rust
    /// use reminisce::{NativeJoystick, Joystick};
    /// let joystick:NativeJoystick = Joystick::new(0).unwrap();
    /// if let Ok(joystick) = joystick {
    ///     println!("{}", joystick.get_id())
    /// } else {
    ///     println!("No joystick plugged in")
    /// }
    /// ```
	fn new(index: u8) -> Result<Self, Self::OpenError>;

	/// Check if the joystick is still connected
	fn is_connected(&self) -> bool;

	/// Get the identifier of this joystick
    ///
    /// This is a cow because it can be a static or owned String depending on the
    /// implementation.
	fn get_id(&self) -> Cow<str>;

	/// Get the index of this joystick
	fn get_index(&self) -> u8;

	/// Get the number of axes this joystick has
    ///
    /// This is capped at 6 axes for now.
	fn get_num_axes(&self) -> u8;

	/// Get the number of buttons this joystick has
    ///
    /// This is capped at 16 buttons currently.
	fn get_num_buttons(&self) -> u8;

    /// Get the battery level of this joystick
    ///
    /// Returns none if the joystick is wired or this operation is not supported
    /// by the backend
    fn get_battery(&self) -> Option<f32>;

    /// Poll the joystick for events in non-blocking mode and return the native event
    /// as returned from the backend
	fn poll_native(&mut self) -> Option<Self::NativeEvent>;

    /// Poll the joystick for events in non-blocking mode
    ///
    /// This runs `self.poll_native()` then converts it into an event using
    /// the `into_event` method.
    fn poll(&mut self) -> Option<Event> {
        self.poll_native().map(|e| e.into_event())
    }

    /// Map the axes and buttons of this joystick by wrapping it in a `JoystickMapper`
    #[cfg(feature = "mappings")]
    fn into_mapper(self) -> JoystickMapper<Self> {
        JoystickMapper::new(self)
    }

    /// Iterate through the events that haven't been processed yet
    fn iter(&mut self) -> Poller<Self> {
        Poller {
            joystick: self
        }
    }

	/// Get the version of this joystick which includes state
    ///
    /// On the Linux backend, a wrapper is made, but on the Windows
    /// backend no wrapper is needed so this just returns the
    ///n `NativeJoystick` structure
	fn with_state(self) -> Self::WithState;
}

/// A joystick that keeps a record of its state
/// This makes it really easy to write the input for games, etc because its just a matter
/// of calling a single method to query where the axes are
///
/// ``` rust
/// use reminisce::{scan, Axis, NativeJoystick, Joystick, StatefulJoystick};
/// let mut joysticks = scan().into_iter().map(|js| js.with_state()).collect::<Vec<_>>();
/// for joystick in &joysticks {
///     let x = joystick.get_axis(Axis::LeftX).unwrap_or(0);
///     let y = joystick.get_axis(Axis::LeftY).unwrap_or(0);
///     println!("{}, {}", x, y)
/// }
/// ```
pub trait StatefulJoystick : Joystick + Sized {
	/// Get the value of a specific axis as an integer between `MIN_AXIS_VALUE` and `MAX_AXIS_VALUE`
	fn get_axis(&self, index: Axis) -> Option<i16>;

	/// Get the value of a specific axis normalised to between -1.0 and 1.0
	fn get_normalised_axis(&self, index: Axis) -> Option<f32> {
		self.get_axis(index).map(|v| v as f32 / MAX_AXIS_VALUE as f32)
	}

	/// Iterate over the axes in this joystick
	fn axes(&self) -> Axes<Self> {
		use std::mem;
		Axes {
			joystick: self,
			axis: unsafe { mem::zeroed() }
		}
	}

	/// Iterate over the buttons in this joystick
	fn buttons(&self) -> Buttons<Self> {
		use std::mem;
		Buttons {
			joystick: self,
			button: unsafe { mem::zeroed() }
		}
	}

	/// Get the value (if it is pressed or not) of a specific button
	///
	/// The first two buttons are usually the accept and back buttons
	fn get_button(&self, index: Button) -> Option<bool>;

	/// Update the state of this joystick by polling the native backend
	fn update(&mut self);
}

/// An iterator over a joystick's axes
pub struct Axes<'a, J> where J:StatefulJoystick+'a {
	joystick: &'a J,
	axis: u8
}
impl<'a, J> Iterator for Axes<'a, J> where J:StatefulJoystick {
	type Item = (Axis, i16);
	fn next(&mut self) -> Option<(Axis, i16)> {
		self.axis += 1;
		let axis = unsafe { cast(self.axis - 1) };
		self.joystick.get_axis(axis).map(|v| (axis, v))
	}
}

/// An iterator over a joystick's buttons
pub struct Buttons<'a, J> where J:StatefulJoystick+'a {
	joystick: &'a J,
	button: u8
}
impl<'a, J> Iterator for Buttons<'a, J> where J:StatefulJoystick {
	type Item = (Button, bool);
	fn next(&mut self) -> Option<(Button, bool)> {
		self.button += 1;
		let button = unsafe { cast(self.button - 1) };
		self.joystick.get_button(button).map(|v| (button, v))
	}
}

/// An iterator over a joystick's event queue
pub struct Poller<'a, J> where J:Joystick+'a {
    joystick: &'a mut J
}

impl<'a, J> Iterator for Poller<'a, J> where J:Joystick {
	type Item = Event;
    /// This calls the `joystick.poll()` method to poll for the next event
	fn next(&mut self) -> Option<Event> {
		self.joystick.poll()
	}
}
<commit_msg>Minor updates to work on Rust beta<commit_after>//! Reminisce is a lightweight library intended to be used for detecting and
//! reading from joysticks.
#![feature(into_cow)]
#![cfg_attr(feature = "mappings", feature(alloc))]
#![cfg_attr(target_os = "linux", feature(libc, fs_walk))]
extern crate libc;
#[cfg(target_os = "windows")]
#[macro_use] extern crate rustc_bitflags;

#[cfg(feature = "sdl")]
extern crate sdl2;

/// Someday, somehow
#[cfg(all(feature = "emscripten", not(feature = "sdl")))]
pub mod emscripten;

#[cfg(all(feature = "emscripten", not(feature = "sdl")))]
pub use emscripten as native;

#[cfg(all(target_os = "linux", not(feature = "sdl")))]
pub mod linux;

#[cfg(all(target_os = "linux", not(feature = "sdl")))]
pub use linux as native;

#[cfg(all(target_os = "windows", not(feature = "sdl")))]
pub mod windows;

#[cfg(all(target_os = "windows", not(feature = "sdl")))]
pub use windows as native;

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

#[cfg(feature = "sdl")]
pub use sdl as native;

#[cfg(feature = "mappings")]
pub mod mapper;

#[cfg(feature = "mappings")]
pub use mapper::JoystickMapper;
pub use native::{NativeJoystick, scan};

/// The maximum axis value
pub static MAX_AXIS_VALUE:i16 = 32767;
/// The minimum axis value
pub static MIN_AXIS_VALUE:i16 = -32767;

use std::borrow::Cow;
use std::error::Error;
use std::fmt::Debug;
use std::mem::transmute as cast;

#[cfg(feature = "mappings")]
macro_rules! text_enum(
    ($name:ident, $($enumer:ident => $text:expr),+) => (
        impl ::std::fmt::Display for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                write!(fmt, "{}", match *self {
                    $($name::$enumer => $text),+
                })
            }
        }
        impl ::std::str::FromStr for $name {
            type Err = String;
            fn from_str(s: &str) -> Result<$name, String> {
                match s {
                    $($text => Ok($name::$enumer),)+
                    _ => Err(format!("Could not make {} from {}", stringify!($name), s))
                }
            }
        }
    )
);
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A direction on a joystick
///
/// This uses the order that Linux drivers and the HTML5 Gamepad API uses so it should ring a bell
pub enum Axis {
	/// The x direction of the left stick
    ///
    /// This is usually used for horizontal movement in a game
    LeftX,
	/// The y direction of the left stick
    ///
    /// This is usually used for vertical movement in a game
    LeftY,
	/// The x direction of the right stick
    //
    /// This is usually used for looking around in a game
    RightX,
	/// The y direction of the right stick
    //
    /// This is usually used for looking around in a game
    RightY,
	/// How far down the left trigger is pressed
    ///
    /// This is only used as a button on some platforms so don't rely on just this
    TriggerLeft,
	/// How far down the right trigger is pressed
    ///
    /// This is only used as a button on some platforms so don't rely on just this
    TriggerRight
}
#[cfg(feature = "mappings")]
text_enum!(Axis,
    LeftX => "leftx",
    LeftY => "lefty",
    RightX => "rightx",
    RightY => "righty",
    TriggerLeft => "triggerleft",
    TriggerRight => "triggerright"
);

#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A button on a joystick
///
/// This uses the order that Linux drivers and the HTML5 Gamepad API uses so it should be familiar
pub enum Button {
	/// The A button
    ///
    /// This is typically used for jumping
	A,
	/// The B button
    ///
    /// This is typically used for hitting
	B,
	/// The X button
	X,
	/// The Y button
	Y,
	/// The left top shoulder button
    ///
    /// This is usually used in FPS games for throwing a certain kind of grenade
	LeftShoulder,
	/// The right top shoulder button
	RightShoulder,
	/// The left bottom shoulder / trigger button
    ///
    /// This is typically used in FPS games for aiming down the sights in a weapon
	LeftTrigger,
	/// The right bottom shoulder / trigger button
    ///
    /// This is typically used in FPS games for shooting with a weapon
	RightTrigger,
	/// The back / select button
    ///
    /// This is usually used as an alternate pause menu or to open a menu in-game.
	Select,
	/// The start / forward button
    ///
    /// This is usually used to start and pause a game
	Start,
	/// The left stick button
	LeftStick,
	/// The right stick button
	RightStick,
	/// The up button on the directional pad
	DPadUp,
	/// The down button on the directional pad
	DPadDown,
	/// The left button on the directional pad
	DPadLeft,
	/// The right button on the directional pad
	DPadRight
}
#[cfg(feature = "mappings")]
text_enum!(Button,
    A => "a",
    B => "b",
    X => "x",
    Y => "y",
    LeftShoulder => "leftshoulder",
    RightShoulder => "rightshoulder",
    LeftTrigger => "lefttrigger",
    RightTrigger => "righttrigger",
    Select => "select",
    Start => "start",
    LeftStick => "leftstick",
    RightStick => "rightstick",
    DPadUp => "dpadup",
    DPadDown => "dpaddown",
    DPadLeft => "dpadleft",
    DPadRight => "dpadright"
);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// An event from a joystick
pub enum Event {
	/// Fired when a button is pressed with the button's index
	ButtonPressed(Button),
	/// Fired when a button is released with the button's index
	ButtonReleased(Button),
	/// Fired when a axis is moved with the axis index and its value,
	/// which is between `MIN_JOYSTICK_VALUE` and `MAX_JOYSTICK_VALUE`
	AxisMoved(Axis, i16)
}
/// Convert a raw event into a Reminisce event
pub trait IntoEvent {
	/// Convert this into a Reminisce event
	fn into_event(self) -> Event;
}

impl IntoEvent for Event {
    /// Convert the event into itself
    ///
    /// The only reason this exists is because windows doesn't have events so the backend has to
    /// make reminisce events directly and pretend that they are the native events.
    fn into_event(self) -> Event {
        self
    }
}

/// A joystick or gamepad
///
/// Each `Joystick` has its own event queue that can be polled repeatedly
/// using the `iter()` method or by calling the `poll()` method repeatedly.
///
/// ``` rust
/// use reminisce::{scan, Axis, Event, Joystick};
/// let mut joysticks = scan();
/// let (mut x, mut y) = (0, 0);
/// for joystick in &mut joysticks {
///     for event in joystick.iter() {
///         match event {
///             Event::AxisMoved(Axis::LeftX, nx) =>
///                 x += nx,
///             Event::AxisMoved(Axis::LeftY, ny) =>
///                 y += ny,
///             _ => ()
///         }
///     }
/// }
/// println!("{}, {}", x, y);
/// ```
pub trait Joystick : Sized {
	/// The version of this joystick that includes the state
    ///
    /// On Linux, this is a wrapper around the joystick, but on Windows,
    /// this is the same stucture because the joystick always includes
    /// state on it.
	type WithState : StatefulJoystick;

    /// The event that this joystick processes
    type NativeEvent: IntoEvent;

    type OpenError: Error + Debug;

	/// Create a new joystick from its index
    ///
    /// If an error occurs, this will return the textual representation of that error.
    ///
    /// ``` rust
    /// use reminisce::{NativeJoystick, Joystick};
    /// let joystick:NativeJoystick = Joystick::new(0).unwrap();
    /// if let Ok(joystick) = joystick {
    ///     println!("{}", joystick.get_id())
    /// } else {
    ///     println!("No joystick plugged in")
    /// }
    /// ```
	fn new(index: u8) -> Result<Self, Self::OpenError>;

	/// Check if the joystick is still connected
	fn is_connected(&self) -> bool;

	/// Get the identifier of this joystick
    ///
    /// This is a cow because it can be a static or owned String depending on the
    /// implementation.
	fn get_id(&self) -> Cow<str>;

	/// Get the index of this joystick
	fn get_index(&self) -> u8;

	/// Get the number of axes this joystick has
    ///
    /// This is capped at 6 axes for now.
	fn get_num_axes(&self) -> u8;

	/// Get the number of buttons this joystick has
    ///
    /// This is capped at 16 buttons currently.
	fn get_num_buttons(&self) -> u8;

    /// Get the battery level of this joystick
    ///
    /// Returns none if the joystick is wired or this operation is not supported
    /// by the backend
    fn get_battery(&self) -> Option<f32>;

    /// Poll the joystick for events in non-blocking mode and return the native event
    /// as returned from the backend
	fn poll_native(&mut self) -> Option<Self::NativeEvent>;

    /// Poll the joystick for events in non-blocking mode
    ///
    /// This runs `self.poll_native()` then converts it into an event using
    /// the `into_event` method.
    fn poll(&mut self) -> Option<Event> {
        self.poll_native().map(|e| e.into_event())
    }

    /// Map the axes and buttons of this joystick by wrapping it in a `JoystickMapper`
    #[cfg(feature = "mappings")]
    fn into_mapper(self) -> JoystickMapper<Self> {
        JoystickMapper::new(self)
    }

    /// Iterate through the events that haven't been processed yet
    fn iter(&mut self) -> Poller<Self> {
        Poller {
            joystick: self
        }
    }

	/// Get the version of this joystick which includes state
    ///
    /// On the Linux backend, a wrapper is made, but on the Windows
    /// backend no wrapper is needed so this just returns the
    ///n `NativeJoystick` structure
	fn with_state(self) -> Self::WithState;
}

/// A joystick that keeps a record of its state
/// This makes it really easy to write the input for games, etc because its just a matter
/// of calling a single method to query where the axes are
///
/// ``` rust
/// use reminisce::{scan, Axis, NativeJoystick, Joystick, StatefulJoystick};
/// let mut joysticks = scan().into_iter().map(|js| js.with_state()).collect::<Vec<_>>();
/// for joystick in &joysticks {
///     let x = joystick.get_axis(Axis::LeftX).unwrap_or(0);
///     let y = joystick.get_axis(Axis::LeftY).unwrap_or(0);
///     println!("{}, {}", x, y)
/// }
/// ```
pub trait StatefulJoystick : Joystick + Sized {
	/// Get the value of a specific axis as an integer between `MIN_AXIS_VALUE` and `MAX_AXIS_VALUE`
	fn get_axis(&self, index: Axis) -> Option<i16>;

	/// Get the value of a specific axis normalised to between -1.0 and 1.0
	fn get_normalised_axis(&self, index: Axis) -> Option<f32> {
		self.get_axis(index).map(|v| v as f32 / MAX_AXIS_VALUE as f32)
	}

	/// Iterate over the axes in this joystick
	fn axes(&self) -> Axes<Self> {
		use std::mem;
		Axes {
			joystick: self,
			axis: unsafe { mem::zeroed() }
		}
	}

	/// Iterate over the buttons in this joystick
	fn buttons(&self) -> Buttons<Self> {
		use std::mem;
		Buttons {
			joystick: self,
			button: unsafe { mem::zeroed() }
		}
	}

	/// Get the value (if it is pressed or not) of a specific button
	///
	/// The first two buttons are usually the accept and back buttons
	fn get_button(&self, index: Button) -> Option<bool>;

	/// Update the state of this joystick by polling the native backend
	fn update(&mut self);
}

/// An iterator over a joystick's axes
pub struct Axes<'a, J> where J:StatefulJoystick+'a {
	joystick: &'a J,
	axis: u8
}
impl<'a, J> Iterator for Axes<'a, J> where J:StatefulJoystick {
	type Item = (Axis, i16);
	fn next(&mut self) -> Option<(Axis, i16)> {
		self.axis += 1;
		let axis = unsafe { cast(self.axis - 1) };
		self.joystick.get_axis(axis).map(|v| (axis, v))
	}
}

/// An iterator over a joystick's buttons
pub struct Buttons<'a, J> where J:StatefulJoystick+'a {
	joystick: &'a J,
	button: u8
}
impl<'a, J> Iterator for Buttons<'a, J> where J:StatefulJoystick {
	type Item = (Button, bool);
	fn next(&mut self) -> Option<(Button, bool)> {
		self.button += 1;
		let button = unsafe { cast(self.button - 1) };
		self.joystick.get_button(button).map(|v| (button, v))
	}
}

/// An iterator over a joystick's event queue
pub struct Poller<'a, J> where J:Joystick+'a {
    joystick: &'a mut J
}

impl<'a, J> Iterator for Poller<'a, J> where J:Joystick {
	type Item = Event;
    /// This calls the `joystick.poll()` method to poll for the next event
	fn next(&mut self) -> Option<Event> {
		self.joystick.poll()
	}
}
<|endoftext|>


<commit_before>use std::borrow::{Borrow, Cow};
use std::env;
use std::marker::PhantomData;
use std::path::Path;
use clap::{self, Arg, SubCommand};
use shlex;

use app::{ClapApp, ClapRun};
use core::{Query, Repository, Workspace};
use core::url::build_url;
use util::{self, process};
use vcs::{self, Vcs};

/// Toplevel application
pub enum Command<'a> {
  Init(InitCommand<'a>),
  Add(AddCommand<'a>),
  Clone(CloneCommand<'a>),
  Sync(SyncCommand<'a>),
  List(ListCommand<'a>),
  Foreach(ForeachCommand<'a>),
}

impl<'a> ClapApp for Command<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.subcommand(InitCommand::make_app(SubCommand::with_name("init")))
       .subcommand(AddCommand::make_app(SubCommand::with_name("add")))
       .subcommand(CloneCommand::make_app(SubCommand::with_name("clone")))
       .subcommand(ListCommand::make_app(SubCommand::with_name("list")))
       .subcommand(ForeachCommand::make_app(SubCommand::with_name("foreach")))
       .subcommand(SyncCommand::make_app(SubCommand::with_name("sync")))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for Command<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> Command<'a> {
    match m.subcommand() {
      ("init", Some(m)) => Command::Init(m.into()),
      ("add", Some(m)) => Command::Add(m.into()),
      ("clone", Some(m)) => Command::Clone(m.into()),
      ("list", Some(m)) => Command::List(m.into()),
      ("foreach", Some(m)) => Command::Foreach(m.into()),
      ("sync", Some(m)) => Command::Sync(m.into()),
      _ => unreachable!(),
    }
  }
}

impl<'a> Command<'a> {
  pub fn run(self) -> ::Result<()> {
    match self {
      Command::Init(m) => m.run(),
      Command::Add(m) => m.run(),
      Command::Clone(m) => m.run(),
      Command::List(m) => m.run(),
      Command::Foreach(m) => m.run(),
      Command::Sync(m) => m.run(),
    }
  }
}

/// subcommand `add`
pub struct AddCommand<'a> {
  path: Option<Vec<&'a Path>>,
  verbose: bool,
  import: bool,
  depth: Option<usize>,
}

impl<'a> ClapApp for AddCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Add existed repository under management")
       .arg_from_usage("[path]...       'Location of local repositories'")
       .arg_from_usage("-v, --verbose   'Use verbose output'")
       .arg_from_usage("-i, --import    'Use import mode'")
       .arg_from_usage("--depth=[depth] 'Maximal depth of entries for each base directory'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for AddCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> AddCommand<'a> {
    AddCommand {
      path: m.values_of("path").map(|s| s.map(Path::new).collect()),
      verbose: m.is_present("verbose"),
      import: m.is_present("import"),
      depth: m.value_of("depth").and_then(|s| s.parse().ok()),
    }
  }
}

impl<'a> ClapRun for AddCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;

    if self.import {
      if let Some(roots) = self.path {
        for root in roots {
          workspace.scan_repositories(root, self.verbose, self.depth)?;
        }
      } else {
        workspace.scan_repositories_default(self.verbose, self.depth)?;
      }
    } else {
      let paths: Vec<Cow<Path>> = if let Some(ref path) =
        self.path {
        path.into_iter().map(|&path| path.into()).collect()
      } else {
        vec![env::current_dir()?.into()]
      };
      for path in paths {
        if vcs::detect_from_path(&path).is_none() {
          println!("Ignored: {} is not a repository", path.display());
          continue;
        }
        if self.verbose {
          println!("Added: {}", util::canonicalize_pretty(&path)?.display());
        }
        let repo = Repository::from_path(path)?;
        workspace.add_repository(repo, false);
      }
    }

    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `new`
pub struct InitCommand<'a> {
  path: Option<&'a Path>,
  vcs: Option<Vcs>,
  posthook: Option<&'a str>,
  dry_run: bool,
}

impl<'a> ClapApp for InitCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Create a new Git repository with intuitive directory structure")
       .arg_from_usage("[path]                'Path of target repository (current directory by default)'")
       .arg(Arg::from_usage("--vcs=[vcs]      'Used Version Control System'")
              .possible_values(Vcs::possible_values()))
       .arg_from_usage("--posthook=[posthook] 'Post hook after initialization'")
       .arg_from_usage("-n, --dry-run         'Do not actually perform commands'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for InitCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> InitCommand<'a> {
    InitCommand {
      path: m.value_of("path").map(Path::new),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      posthook: m.value_of("posthook"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for InitCommand<'a> {
  fn run(self) -> ::Result<()> {
    let path: Cow<Path> = {
      self.path
          .map(Into::into)
          .map(Result::Ok)
          .unwrap_or_else(|| env::current_dir().map(Into::into))?
    };
    if vcs::detect_from_path(&path).is_some() {
      println!("The repository {} has already existed.", path.display());
      return Ok(());
    }

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    let posthook = self.posthook.and_then(|s| shlex::split(s));

    print!("Creating an empty repository at \"{}\"", path.display());
    print!(" (VCS: {:?})", vcs);
    println!();

    if !self.dry_run {
      vcs.do_init(&path)?;
      if let Some(posthook) = posthook {
        if posthook.len() >= 1 {
          let command = posthook[0].clone();
          let args: Vec<_> = posthook.into_iter().skip(1).collect();
          process::inherit(&command).args(args)
            .current_dir(&path)
            .status()?;
        }
      }

      let repo = Repository::from_path(path)?;

      let mut workspace = Workspace::new(None)?;
      workspace.add_repository(repo, false);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `clone`
pub struct CloneCommand<'a> {
  query: Query,
  dest: Option<&'a Path>,
  root: Option<&'a Path>,
  ssh: bool,
  arg: Option<&'a str>,
  vcs: Option<Vcs>,
  dry_run: bool,
}

impl<'a> ClapApp for CloneCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Clone remote repositories, and then add it under management")
       .arg_from_usage("<query>         'an URL or a string to determine the URL of remote repository'")
       .arg_from_usage("[dest]          'Destination directory of cloned repository'")
       .arg_from_usage("--root=[root]   'Path to determine the destination directory of cloned repository'")
       .arg_from_usage("-s, --ssh       'Use SSH protocol'")
       .arg_from_usage("--arg=[arg]     'Supplemental arguments for VCS command'")
       .arg(Arg::from_usage("--vcs=[vcs] 'Used Version Control System'").possible_values(Vcs::possible_values()))
       .arg_from_usage("-n, --dry-run   'Do not actually execute VCS command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for CloneCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> CloneCommand<'a> {
    CloneCommand {
      query: m.value_of("query")
              .and_then(|s| s.parse().ok())
              .unwrap(),
      dest: m.value_of("dest").map(Path::new),
      root: m.value_of("root").map(Path::new),
      ssh: m.is_present("ssh"),
      arg: m.value_of("arg"),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for CloneCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(self.root)?;

    let dest: Cow<Path> = if let Some(dest) = self.dest {
      dest.into()
    } else {
      let host = self.query.host().unwrap_or("github.com");
      let path = self.query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    };
    if vcs::detect_from_path(&dest).is_some() {
      println!("The repository {} has already existed.", dest.display());
      return Ok(());
    }

    let url = build_url(&self.query, self.ssh)?;

    let args = self.arg
                   .and_then(|s| shlex::split(s))
                   .unwrap_or_default();

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    println!("Clone from {} into {} by using {:?} (with arguments: {})",
             url,
             dest.display(),
             vcs,
             util::join_str(&args),
    );

    if !self.dry_run {
      vcs.do_clone(&dest, &url, &args)?;

      let mut repo = Repository::from_path(dest)?;
      repo.set_url(url);
      workspace.add_repository(repo, false);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subommand `sync`
pub struct SyncCommand<'a> {
  verbose: bool,
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for SyncCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Scan directories to create cache of repositories list")
       .arg_from_usage("-v, --verbose 'Use verbose output'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for SyncCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> SyncCommand<'a> {
    SyncCommand {
      verbose: m.is_present("verbose"),
      marker: PhantomData,
    }
  }
}

impl<'a> ClapRun for SyncCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;
    workspace.drop_invalid_repositories(self.verbose);
    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `list`
pub struct ListCommand<'a> {
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ListCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("List local repositories managed by rhq")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ListCommand<'a> {
  fn from(_: &'b clap::ArgMatches<'a>) -> ListCommand<'a> {
    ListCommand { marker: PhantomData }
  }
}

impl<'a> ClapRun for ListCommand<'a> {
  fn run(self) -> ::Result<()> {
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      println!("{}", repo.path_string());
    }
    Ok(())
  }
}

/// Subcommand `foreach`
pub struct ForeachCommand<'a> {
  command: &'a str,
  args: Option<clap::Values<'a>>,
  dry_run: bool,
}

impl<'a> ClapApp for ForeachCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Execute command into each repositories")
       .arg_from_usage("<command>       'Command name'")
       .arg_from_usage("[args]...       'Arguments of command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ForeachCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ForeachCommand<'a> {
    ForeachCommand {
      command: m.value_of("command").unwrap(),
      args: m.values_of("args"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for ForeachCommand<'a> {
  fn run(self) -> ::Result<()> {
    let args: Vec<_> = self.args.map(|s| s.collect()).unwrap_or_default();
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      if self.dry_run {
        println!("+ {} {}", self.command, util::join_str(&args));
      } else {
        repo.run_command(self.command, &args)?;
      }
    }
    Ok(())
  }
}
<commit_msg>scan -> refresh<commit_after>use std::borrow::{Borrow, Cow};
use std::env;
use std::marker::PhantomData;
use std::path::Path;
use clap::{self, Arg, SubCommand};
use shlex;

use app::{ClapApp, ClapRun};
use core::{Query, Repository, Workspace};
use core::url::build_url;
use util::{self, process};
use vcs::{self, Vcs};

/// Toplevel application
pub enum Command<'a> {
  Init(InitCommand<'a>),
  Add(AddCommand<'a>),
  Clone(CloneCommand<'a>),
  Refresh(RefreshCommand<'a>),
  List(ListCommand<'a>),
  Foreach(ForeachCommand<'a>),
}

impl<'a> ClapApp for Command<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.subcommand(AddCommand::make_app(SubCommand::with_name("add")))
       .subcommand(RefreshCommand::make_app(SubCommand::with_name("refresh")))
       .subcommand(InitCommand::make_app(SubCommand::with_name("init")))
       .subcommand(CloneCommand::make_app(SubCommand::with_name("clone")))
       .subcommand(ListCommand::make_app(SubCommand::with_name("list")))
       .subcommand(ForeachCommand::make_app(SubCommand::with_name("foreach")))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for Command<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> Command<'a> {
    match m.subcommand() {
      ("add", Some(m)) => Command::Add(m.into()),
      ("refresh", Some(m)) => Command::Refresh(m.into()),
      ("init", Some(m)) => Command::Init(m.into()),
      ("clone", Some(m)) => Command::Clone(m.into()),
      ("list", Some(m)) => Command::List(m.into()),
      ("foreach", Some(m)) => Command::Foreach(m.into()),
      _ => unreachable!(),
    }
  }
}

impl<'a> Command<'a> {
  pub fn run(self) -> ::Result<()> {
    match self {
      Command::Refresh(m) => m.run(),
      Command::Add(m) => m.run(),
      Command::Init(m) => m.run(),
      Command::Clone(m) => m.run(),
      Command::List(m) => m.run(),
      Command::Foreach(m) => m.run(),
    }
  }
}

/// subcommand `add`
pub struct AddCommand<'a> {
  path: Option<Vec<&'a Path>>,
  verbose: bool,
  import: bool,
  depth: Option<usize>,
}

impl<'a> ClapApp for AddCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Add existed repositories into management")
       .arg_from_usage("[path]...       'Location of local repositories'")
       .arg_from_usage("-v, --verbose   'Use verbose output'")
       .arg_from_usage("-i, --import    'Use import mode'")
       .arg_from_usage("--depth=[depth] 'Maximal depth of entries for each base directory'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for AddCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> AddCommand<'a> {
    AddCommand {
      path: m.values_of("path").map(|s| s.map(Path::new).collect()),
      verbose: m.is_present("verbose"),
      import: m.is_present("import"),
      depth: m.value_of("depth").and_then(|s| s.parse().ok()),
    }
  }
}

impl<'a> ClapRun for AddCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;

    if self.import {
      if let Some(roots) = self.path {
        for root in roots {
          workspace.scan_repositories(root, self.verbose, self.depth)?;
        }
      } else {
        workspace.scan_repositories_default(self.verbose, self.depth)?;
      }
    } else {
      let paths: Vec<Cow<Path>> = if let Some(ref path) =
        self.path {
        path.into_iter().map(|&path| path.into()).collect()
      } else {
        vec![env::current_dir()?.into()]
      };
      for path in paths {
        if vcs::detect_from_path(&path).is_none() {
          println!("Ignored: {} is not a repository", path.display());
          continue;
        }
        if self.verbose {
          println!("Added: {}", util::canonicalize_pretty(&path)?.display());
        }
        let repo = Repository::from_path(path)?;
        workspace.add_repository(repo, false);
      }
    }

    workspace.save_cache()?;
    Ok(())
  }
}

/// Subommand `refresh`
pub struct RefreshCommand<'a> {
  verbose: bool,
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for RefreshCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Scan repository list and drop if it is not existed or matches exclude pattern.")
       .arg_from_usage("-v, --verbose 'Use verbose output'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for RefreshCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> RefreshCommand<'a> {
    RefreshCommand {
      verbose: m.is_present("verbose"),
      marker: PhantomData,
    }
  }
}

impl<'a> ClapRun for RefreshCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;
    workspace.drop_invalid_repositories(self.verbose);
    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `new`
pub struct InitCommand<'a> {
  path: Option<&'a Path>,
  vcs: Option<Vcs>,
  posthook: Option<&'a str>,
  dry_run: bool,
}

impl<'a> ClapApp for InitCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Create a new Git repository with intuitive directory structure")
       .arg_from_usage("[path]                'Path of target repository (current directory by default)'")
       .arg(Arg::from_usage("--vcs=[vcs]      'Used Version Control System'")
              .possible_values(Vcs::possible_values()))
       .arg_from_usage("--posthook=[posthook] 'Post hook after initialization'")
       .arg_from_usage("-n, --dry-run         'Do not actually perform commands'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for InitCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> InitCommand<'a> {
    InitCommand {
      path: m.value_of("path").map(Path::new),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      posthook: m.value_of("posthook"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for InitCommand<'a> {
  fn run(self) -> ::Result<()> {
    let path: Cow<Path> = {
      self.path
          .map(Into::into)
          .map(Result::Ok)
          .unwrap_or_else(|| env::current_dir().map(Into::into))?
    };
    if vcs::detect_from_path(&path).is_some() {
      println!("The repository {} has already existed.", path.display());
      return Ok(());
    }

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    let posthook = self.posthook.and_then(|s| shlex::split(s));

    print!("Creating an empty repository at \"{}\"", path.display());
    print!(" (VCS: {:?})", vcs);
    println!();

    if !self.dry_run {
      vcs.do_init(&path)?;
      if let Some(posthook) = posthook {
        if posthook.len() >= 1 {
          let command = posthook[0].clone();
          let args: Vec<_> = posthook.into_iter().skip(1).collect();
          process::inherit(&command).args(args)
            .current_dir(&path)
            .status()?;
        }
      }

      let repo = Repository::from_path(path)?;

      let mut workspace = Workspace::new(None)?;
      workspace.add_repository(repo, false);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `clone`
pub struct CloneCommand<'a> {
  query: Query,
  dest: Option<&'a Path>,
  root: Option<&'a Path>,
  ssh: bool,
  arg: Option<&'a str>,
  vcs: Option<Vcs>,
  dry_run: bool,
}

impl<'a> ClapApp for CloneCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Clone remote repositories, and then add it under management")
       .arg_from_usage("<query>         'an URL or a string to determine the URL of remote repository'")
       .arg_from_usage("[dest]          'Destination directory of cloned repository'")
       .arg_from_usage("--root=[root]   'Path to determine the destination directory of cloned repository'")
       .arg_from_usage("-s, --ssh       'Use SSH protocol'")
       .arg_from_usage("--arg=[arg]     'Supplemental arguments for VCS command'")
       .arg(Arg::from_usage("--vcs=[vcs] 'Used Version Control System'").possible_values(Vcs::possible_values()))
       .arg_from_usage("-n, --dry-run   'Do not actually execute VCS command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for CloneCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> CloneCommand<'a> {
    CloneCommand {
      query: m.value_of("query")
              .and_then(|s| s.parse().ok())
              .unwrap(),
      dest: m.value_of("dest").map(Path::new),
      root: m.value_of("root").map(Path::new),
      ssh: m.is_present("ssh"),
      arg: m.value_of("arg"),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for CloneCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(self.root)?;

    let dest: Cow<Path> = if let Some(dest) = self.dest {
      dest.into()
    } else {
      let host = self.query.host().unwrap_or("github.com");
      let path = self.query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    };
    if vcs::detect_from_path(&dest).is_some() {
      println!("The repository {} has already existed.", dest.display());
      return Ok(());
    }

    let url = build_url(&self.query, self.ssh)?;

    let args = self.arg
                   .and_then(|s| shlex::split(s))
                   .unwrap_or_default();

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    println!("Clone from {} into {} by using {:?} (with arguments: {})",
             url,
             dest.display(),
             vcs,
             util::join_str(&args),
    );

    if !self.dry_run {
      vcs.do_clone(&dest, &url, &args)?;

      let mut repo = Repository::from_path(dest)?;
      repo.set_url(url);
      workspace.add_repository(repo, false);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `list`
pub struct ListCommand<'a> {
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ListCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("List local repositories managed by rhq")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ListCommand<'a> {
  fn from(_: &'b clap::ArgMatches<'a>) -> ListCommand<'a> {
    ListCommand { marker: PhantomData }
  }
}

impl<'a> ClapRun for ListCommand<'a> {
  fn run(self) -> ::Result<()> {
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      println!("{}", repo.path_string());
    }
    Ok(())
  }
}

/// Subcommand `foreach`
pub struct ForeachCommand<'a> {
  command: &'a str,
  args: Option<clap::Values<'a>>,
  dry_run: bool,
}

impl<'a> ClapApp for ForeachCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Execute command into each repositories")
       .arg_from_usage("<command>       'Command name'")
       .arg_from_usage("[args]...       'Arguments of command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ForeachCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ForeachCommand<'a> {
    ForeachCommand {
      command: m.value_of("command").unwrap(),
      args: m.values_of("args"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for ForeachCommand<'a> {
  fn run(self) -> ::Result<()> {
    let args: Vec<_> = self.args.map(|s| s.collect()).unwrap_or_default();
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      if self.dry_run {
        println!("+ {} {}", self.command, util::join_str(&args));
      } else {
        repo.run_command(self.command, &args)?;
      }
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>use rand::Rng;
use multi_objective::MultiObjective;
use domination::Domination;
use sort::FastNonDominatedSorter;
use crowding_distance::{crowding_distance_assignment, CrowdingDistanceAssignment};
use std::cmp::{self, Ordering};

pub trait SelectSolutions<T, F>: Sized
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    /// Select `n` out of the `solutions`, assigning rank and distance using `objectives`.
    /// `rng` might not be used.
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        rng: &mut R,
    ) where
        R: Rng;
}

/// Uses the approach NSGA takes.
pub struct SelectNSGA;

impl<T, F> SelectSolutions<T, F> for SelectNSGA
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        _rng: &mut R,
    ) where
        R: Rng,
    {
        assert!(objectives.len() > 0);

        // We can select at most `select_n` solutions.
        let mut missing = cmp::min(solutions.len(), select_n);

        // make sure all solutions are unselected
        for s in solutions.iter_mut() {
            s.unselect();
        }

        let pareto_fronts = FastNonDominatedSorter::new(solutions, &|s| s.fitness(), objectives);

        for (rank, mut front) in pareto_fronts.enumerate() {
            assert!(missing > 0);

            // assign rank and crowding distance of those solutions in `front`.
            let _ = crowding_distance_assignment(solutions, &mut front, rank as u32, objectives);

            if front.len() <= missing {
                // whole front fits into result. XXX: should we sort?

                for i in front.into_iter() {
                    solutions[i].select();
                    assert!(missing > 0);
                    missing -= 1;
                }

                if missing == 0 {
                    break;
                }
            } else {
                // choose only best from this front, according to the crowding distance.
                front.sort_by(|&a, &b| {
                    debug_assert!(solutions[a].rank() == solutions[b].rank());
                    if solutions[a].has_better_rank_and_crowding(&solutions[b]) {
                        Ordering::Less
                    } else if solutions[b].has_better_rank_and_crowding(&solutions[a]) {
                        Ordering::Greater
                    } else {
                        Ordering::Equal
                    }
                });

                for i in front.into_iter().take(missing) {
                    assert!(missing > 0);
                    solutions[i].select();
                    missing -= 1;
                }

                assert!(missing == 0);
                break;
            }
        }
    }
}

/// Selection using NSGP as described in [1].
///
/// [1]: Multi-objective genetic programming with redundancy-regulations for automatic construction
/// of image feature extractors.  Watchareeruetai, Ukrit and Matsumoto, Tetsuya and Takeuchi,
/// Yoshinori and Hiroaki, KUDO and Ohnishi, Noboru.  2010
pub struct SelectNSGP {
    pub objective_eps: f64,
}

impl<T, F> SelectSolutions<T, F> for SelectNSGP
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        rng: &mut R,
    ) where
        R: Rng,
    {
        assert!(objectives.len() > 0);

        // We can select at most `select_n` solutions.
        let mut missing = cmp::min(solutions.len(), select_n);

        // make sure all solutions are unselected
        for s in solutions.iter_mut() {
            s.unselect();
        }

        let pareto_fronts = FastNonDominatedSorter::new(solutions, &|s| s.fitness(), objectives);

        let mut fronts_grouped: Vec<Vec<Vec<_>>> = Vec::new();
        for (rank, mut front) in pareto_fronts.enumerate() {

            // first assign rank and crowding distance of those solutions in `front`.
            let min_max_distances =
                crowding_distance_assignment(solutions, &mut front, rank as u32, objectives);
            debug_assert!(min_max_distances.len() == objectives.len());

            // then group this front into individuals with similar (or equal) fitness.
            let mut groups: Vec<Vec<usize>> = Vec::new();

            'group: for idx in front {
                // insert `idx` into a group.
                // test fitness of `idx` (solutions[idx]) against a member of each group.
                // if none fits, create a new group.

                let fitness = solutions[idx].fitness();
                for grp in groups.iter_mut() {
                    let cmp_idx = grp[0];

                    if fitness.similar_to(
                        solutions[cmp_idx].fitness(),
                        &objectives,
                        &min_max_distances,
                        self.objective_eps,
                    )
                    {
                        grp.push(idx);
                        continue 'group;
                    }
                }

                // create a new group
                groups.push(vec![idx]);
            }

            // update the crowding_distance within each group. simply take the average.
            // also record the number of points in the group within each individual's fitness. this
            // is required for sexual selection.
            for grp in groups.iter_mut() {
                // use same average crowding distance for each point in the group
                assert!(grp.len() > 0);
                let avg: f64 = grp.iter().map(|&idx| solutions[idx].dist()).fold(
                    0.0,
                    |acc, x| acc + x,
                ) / grp.len() as f64;
                for &idx in grp.iter() {
                    solutions[idx].set_dist(avg);
                    solutions[idx].set_crowd(grp.len());
                }

                // sort grp according to primary fitness
                grp.sort_by(|&a, &b| {
                    solutions[a].fitness().cmp_objective(
                        solutions[b].fitness(),
                        objectives[0],
                    )
                });
            }

            // group fronts, so that the first group is the one which contains
            // the best individual of fitness objective #0. this makes
            // sure that we always ever include the elite
            groups.sort_by(|a, b| {
                solutions[a[0]].fitness().cmp_objective(
                    solutions[b[0]].fitness(),
                    objectives[0],
                )
            });

            fronts_grouped.push(groups);
        }

        // Each pareto_front has now been grouped into individuals of same (or similar) fitness.
        // Now go through each front, and in each front, choose exactly one individual
        // from each group. Then go to the next front etc. once we are through all
        // fronts, continue with the first and so on, until enough individuals are selected.

        let mut round = 0;
        'outer: while missing > 0 {
            for (front_i, current_front) in fronts_grouped.iter_mut().enumerate() {
                // select up to `missing` solutions from current_front, but from each group only one
                // (which is choosen randomly).
                for (grp_i, grp) in current_front.iter_mut().enumerate() {
                    if missing > 0 {
                        let i = if round == 0 && front_i == 0 && grp_i == 0 {
                            // first round, first group and non-dominated front.
                            // Use always the best according to 0th objective.
                            0
                        } else {
                            // Select randomly
                            rng.gen_range(0, grp.len())
                        };
                        // remove `i`th element from grp returning the solution index
                        let idx = grp.swap_remove(i);
                        assert!(solutions[idx].is_selected() == false);
                        solutions[idx].select();
                        missing -= 1;
                    } else {
                        break 'outer;
                    }
                }

                // only retain groups which are non-empty
                current_front.retain(|grp| grp.len() > 0);
            }
            round += 1;
        }
    }
}

/// Selection using a modified version of NSGP [1].
pub struct SelectNSGPMod {
    pub objective_eps: f64,
}

impl<T, F> SelectSolutions<T, F> for SelectNSGPMod
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        rng: &mut R,
    ) where
        R: Rng,
    {
        assert!(objectives.len() > 0);

        // We can select at most `select_n` solutions.
        let mut missing = cmp::min(solutions.len(), select_n);

        // make sure all solutions are unselected
        for s in solutions.iter_mut() {
            s.unselect();
        }

        let pareto_fronts = FastNonDominatedSorter::new(solutions, &|s| s.fitness(), objectives);

        let mut fronts_grouped: Vec<Vec<Vec<Vec<_>>>> = Vec::new();
        for (rank, mut front) in pareto_fronts.enumerate() {
            // first assign rank and crowding distance of
            // those solutions in `front`.
            let min_max_distances =
                crowding_distance_assignment(solutions, &mut front, rank as u32, objectives);
            debug_assert!(min_max_distances.len() == objectives.len());

            // then group this front into individuals with similar (or equal) fitness.
            // we have one group per objective
            let mut objective_groups = Vec::new();

            for (&obj, &min_max) in objectives.iter().zip(min_max_distances.iter()) {
                let mut groups: Vec<Vec<usize>> = Vec::new();

                'group: for &idx in front.iter() {
                    // insert `idx` into a group.
                    // test fitness of `idx` (solutions[idx]) against a member of each group.
                    // if none fits, create a new group.

                    let fitness = solutions[idx].fitness();
                    for grp in groups.iter_mut() {
                        let cmp_idx = grp[0];

                        if fitness.similar_to(
                            solutions[cmp_idx].fitness(),
                            &[obj],
                            &[min_max],
                            self.objective_eps,
                        )
                        {
                            grp.push(idx);
                            continue 'group;
                        }
                    }

                    // create a new group
                    groups.push(vec![idx]);
                }

                // update the crowding_distance within each group. simply take the average.
                // also record the number of points in the group within each individual's fitness. this
                // is required for sexual selection.
                for grp in groups.iter_mut() {
                    // use same average crowding distance for each point in the group
                    assert!(grp.len() > 0);
                    let avg: f64 = grp.iter().map(|&idx| solutions[idx].dist()).fold(
                        0.0,
                        |acc, x| acc + x,
                    ) / grp.len() as f64;
                    for &idx in grp.iter() {
                        solutions[idx].set_dist(avg);
                        solutions[idx].set_crowd(grp.len()); // XXX
                    }

                    // sort grp according to objective
                    grp.sort_by(|&a, &b| {
                        solutions[a].fitness().cmp_objective(
                            solutions[b].fitness(),
                            obj,
                        )
                    });
                }

                // group fronts, so that the first group is the one which contains
                // the best individual of fitness objective #0. this makes
                // sure that we always ever include the elite
                groups.sort_by(|a, b| {
                    solutions[a[0]].fitness().cmp_objective(
                        solutions[b[0]].fitness(),
                        obj,
                    )
                });

                objective_groups.push(groups);
            }

            fronts_grouped.push(objective_groups);
        }

        // Each pareto_front has now been grouped into individuals of same (or similar) fitness.
        // Now go through each front, and in each front, choose exactly one individual
        // from each group. Then go to the next front etc. once we are through all
        // fronts, continue with the first and so on, until enough individuals are selected.
        // XXX

        let mut round = 0;
        'outer: while missing > 0 {
            for (front_i, current_front) in fronts_grouped.iter_mut().enumerate() {
                // select up to `missing` solutions from current_front, but from each group only one
                // (which is choosen randomly).
                for objective_grp in current_front.iter_mut() {
                    'next_group: for (grp_i, grp) in objective_grp.iter_mut().enumerate() {
                        if missing > 0 {
                            loop {
                                if grp.is_empty() {
                                    break;
                                }
                                //let i = if round == 0 && front_i == 0 && grp_i == 0 { // XXX?
                                // first round, first group and non-dominated front. Use always the best according
                                // to 0th objective.
                                let i = rng.gen_range(0, grp.len());
                                //} else {
                                // Select randomly
                                //rng.gen_range(0, grp.len())
                                //};
                                let idx = grp.swap_remove(i); // remove `i`th element from grp returning the solution index
                                if !solutions[idx].is_selected() {
                                    solutions[idx].select();
                                    missing -= 1;
                                    break;
                                }
                            }
                        } else {
                            break 'outer;
                        }
                    }
                }

                // only retain groups which are non-empty
                current_front.retain(|grp| grp.len() > 0);
            }
            round += 1;
        }
    }
}

/// Select the best individual out of `k` randomly choosen.
/// This gives individuals with better fitness a higher chance to reproduce.
/// `n` is the total number of individuals.
///
/// NOTE: We are not using `sample(rng, 0..n, k)` as it is *very* expensive.
/// Instead we call `rng.gen_range()` k-times. The drawn items could be the same,
/// but the probability is very low if `n` is high compared to `k`.
#[inline]
pub fn tournament_selection_fast<R: Rng, F>(
    rng: &mut R,
    better_than: F,
    n: usize,
    k: usize,
) -> usize
where
    F: Fn(usize, usize) -> bool,
{
    assert!(n > 0);
    assert!(k > 0);
    assert!(n >= k);

    let mut best: usize = rng.gen_range(0, n);

    for _ in 1..k {
        let i = rng.gen_range(0, n);
        if better_than(i, best) {
            best = i;
        }
    }

    return best;
}
<commit_msg>Cleanup<commit_after>use rand::Rng;
use multi_objective::MultiObjective;
use domination::Domination;
use sort::FastNonDominatedSorter;
use crowding_distance::{crowding_distance_assignment, CrowdingDistanceAssignment};
use std::cmp::{self, Ordering};

pub trait SelectSolutions<T, F>: Sized
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    /// Select `n` out of the `solutions`, assigning rank and distance using `objectives`.
    /// `rng` might not be used.
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        rng: &mut R,
    ) where
        R: Rng;
}

/// Uses the approach NSGA takes.
pub struct SelectNSGA;

impl<T, F> SelectSolutions<T, F> for SelectNSGA
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        _rng: &mut R,
    ) where
        R: Rng,
    {
        assert!(objectives.len() > 0);

        // We can select at most `select_n` solutions.
        let mut missing = cmp::min(solutions.len(), select_n);

        // make sure all solutions are unselected
        for s in solutions.iter_mut() {
            s.unselect();
        }

        let pareto_fronts = FastNonDominatedSorter::new(solutions, &|s| s.fitness(), objectives);

        for (rank, mut front) in pareto_fronts.enumerate() {
            assert!(missing > 0);

            // assign rank and crowding distance of those solutions in `front`.
            let _ = crowding_distance_assignment(solutions, &mut front, rank as u32, objectives);

            if front.len() <= missing {
                // whole front fits into result. XXX: should we sort?

                for i in front.into_iter() {
                    solutions[i].select();
                    assert!(missing > 0);
                    missing -= 1;
                }

                if missing == 0 {
                    break;
                }
            } else {
                // choose only best from this front, according to the crowding distance.
                front.sort_by(|&a, &b| {
                    debug_assert!(solutions[a].rank() == solutions[b].rank());
                    if solutions[a].has_better_rank_and_crowding(&solutions[b]) {
                        Ordering::Less
                    } else if solutions[b].has_better_rank_and_crowding(&solutions[a]) {
                        Ordering::Greater
                    } else {
                        Ordering::Equal
                    }
                });

                for i in front.into_iter().take(missing) {
                    assert!(missing > 0);
                    solutions[i].select();
                    missing -= 1;
                }

                assert!(missing == 0);
                break;
            }
        }
    }
}

/// Selection using NSGP as described in [1].
///
/// [1]: Multi-objective genetic programming with redundancy-regulations for automatic construction
/// of image feature extractors.  Watchareeruetai, Ukrit and Matsumoto, Tetsuya and Takeuchi,
/// Yoshinori and Hiroaki, KUDO and Ohnishi, Noboru.  2010
pub struct SelectNSGP {
    pub objective_eps: f64,
}

impl<T, F> SelectSolutions<T, F> for SelectNSGP
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        rng: &mut R,
    ) where
        R: Rng,
    {
        assert!(objectives.len() > 0);

        // We can select at most `select_n` solutions.
        let mut missing = cmp::min(solutions.len(), select_n);

        // make sure all solutions are unselected
        for s in solutions.iter_mut() {
            s.unselect();
        }

        let pareto_fronts = FastNonDominatedSorter::new(solutions, &|s| s.fitness(), objectives);

        let mut fronts_grouped: Vec<Vec<Vec<_>>> = Vec::new();
        for (rank, mut front) in pareto_fronts.enumerate() {

            // first assign rank and crowding distance of those solutions in `front`.
            let min_max_distances =
                crowding_distance_assignment(solutions, &mut front, rank as u32, objectives);
            debug_assert!(min_max_distances.len() == objectives.len());

            // then group this front into individuals with similar (or equal) fitness.
            let mut groups: Vec<Vec<usize>> = Vec::new();

            'group: for idx in front {
                // insert `idx` into a group.
                // test fitness of `idx` (solutions[idx]) against a member of each group.
                // if none fits, create a new group.

                let fitness = solutions[idx].fitness();
                for grp in groups.iter_mut() {
                    let cmp_idx = grp[0];

                    if fitness.similar_to(
                        solutions[cmp_idx].fitness(),
                        &objectives,
                        &min_max_distances,
                        self.objective_eps,
                    )
                    {
                        grp.push(idx);
                        continue 'group;
                    }
                }

                // create a new group
                groups.push(vec![idx]);
            }

            // update the crowding_distance within each group. simply take the average.
            // also record the number of points in the group within each individual's fitness. this
            // is required for sexual selection.
            for grp in groups.iter_mut() {
                // use same average crowding distance for each point in the group
                assert!(grp.len() > 0);
                let avg: f64 = grp.iter().map(|&idx| solutions[idx].dist()).fold(
                    0.0,
                    |acc, x| acc + x,
                ) / grp.len() as f64;
                for &idx in grp.iter() {
                    solutions[idx].set_dist(avg);
                    solutions[idx].set_crowd(grp.len());
                }

                // sort grp according to primary fitness
                grp.sort_by(|&a, &b| {
                    solutions[a].fitness().cmp_objective(
                        solutions[b].fitness(),
                        objectives[0],
                    )
                });
            }

            // group fronts, so that the first group is the one which contains
            // the best individual of fitness objective #0. this makes
            // sure that we always ever include the elite
            groups.sort_by(|a, b| {
                solutions[a[0]].fitness().cmp_objective(
                    solutions[b[0]].fitness(),
                    objectives[0],
                )
            });

            fronts_grouped.push(groups);
        }

        // Each pareto_front has now been grouped into individuals of same (or similar) fitness.
        // Now go through each front, and in each front, choose exactly one individual
        // from each group. Then go to the next front etc. once we are through all
        // fronts, continue with the first and so on, until enough individuals are selected.

        let mut round = 0;
        'outer: while missing > 0 {
            for (front_i, current_front) in fronts_grouped.iter_mut().enumerate() {
                // select up to `missing` solutions from current_front, but from each group only one
                // (which is choosen randomly).
                for (grp_i, grp) in current_front.iter_mut().enumerate() {
                    if missing > 0 {
                        let i = if round == 0 && front_i == 0 && grp_i == 0 {
                            // first round, first group and non-dominated front.
                            // Use always the best according to 0th objective.
                            0
                        } else {
                            // Select randomly
                            rng.gen_range(0, grp.len())
                        };
                        // remove `i`th element from grp returning the solution index
                        let idx = grp.swap_remove(i);
                        assert!(solutions[idx].is_selected() == false);
                        solutions[idx].select();
                        missing -= 1;
                    } else {
                        break 'outer;
                    }
                }

                // only retain groups which are non-empty
                current_front.retain(|grp| grp.len() > 0);
            }
            round += 1;
        }
    }
}

/// Selection using a modified version of NSGP [1].
pub struct SelectNSGPMod {
    pub objective_eps: f64,
}

impl<T, F> SelectSolutions<T, F> for SelectNSGPMod
where
    T: CrowdingDistanceAssignment<F>,
    F: MultiObjective + Domination,
{
    fn select_solutions<R>(
        &self,
        solutions: &mut [T],
        select_n: usize,
        objectives: &[usize],
        rng: &mut R,
    ) where
        R: Rng,
    {
        assert!(objectives.len() > 0);

        // We can select at most `select_n` solutions.
        let mut missing = cmp::min(solutions.len(), select_n);

        // make sure all solutions are unselected
        for s in solutions.iter_mut() {
            s.unselect();
        }

        let pareto_fronts = FastNonDominatedSorter::new(solutions, &|s| s.fitness(), objectives);

        let mut fronts_grouped: Vec<Vec<Vec<Vec<_>>>> = Vec::new();
        for (rank, mut front) in pareto_fronts.enumerate() {
            // first assign rank and crowding distance of
            // those solutions in `front`.
            let min_max_distances =
                crowding_distance_assignment(solutions, &mut front, rank as u32, objectives);
            debug_assert!(min_max_distances.len() == objectives.len());

            // then group this front into individuals with similar (or equal) fitness.
            // we have one group per objective
            let mut objective_groups = Vec::new();

            for (&obj, &min_max) in objectives.iter().zip(min_max_distances.iter()) {
                let mut groups: Vec<Vec<usize>> = Vec::new();

                'group: for &idx in front.iter() {
                    // insert `idx` into a group.
                    // test fitness of `idx` (solutions[idx]) against a member of each group.
                    // if none fits, create a new group.

                    let fitness = solutions[idx].fitness();
                    for grp in groups.iter_mut() {
                        let cmp_idx = grp[0];

                        if fitness.similar_to(
                            solutions[cmp_idx].fitness(),
                            &[obj],
                            &[min_max],
                            self.objective_eps,
                        )
                        {
                            grp.push(idx);
                            continue 'group;
                        }
                    }

                    // create a new group
                    groups.push(vec![idx]);
                }

                // update the crowding_distance within each group. simply take the average.
                // also record the number of points in the group within each individual's fitness. this
                // is required for sexual selection.
                for grp in groups.iter_mut() {
                    // use same average crowding distance for each point in the group
                    assert!(grp.len() > 0);
                    let avg: f64 = grp.iter().map(|&idx| solutions[idx].dist()).fold(
                        0.0,
                        |acc, x| acc + x,
                    ) / grp.len() as f64;
                    for &idx in grp.iter() {
                        solutions[idx].set_dist(avg);
                        solutions[idx].set_crowd(grp.len()); // XXX
                    }

                    // sort grp according to objective
                    grp.sort_by(|&a, &b| {
                        solutions[a].fitness().cmp_objective(
                            solutions[b].fitness(),
                            obj,
                        )
                    });
                }

                // group fronts, so that the first group is the one which contains
                // the best individual of fitness objective #0. this makes
                // sure that we always ever include the elite
                groups.sort_by(|a, b| {
                    solutions[a[0]].fitness().cmp_objective(
                        solutions[b[0]].fitness(),
                        obj,
                    )
                });

                objective_groups.push(groups);
            }

            fronts_grouped.push(objective_groups);
        }

        // Each pareto_front has now been grouped into individuals of same (or similar) fitness.
        // Now go through each front, and in each front, choose exactly one individual
        // from each group. Then go to the next front etc. once we are through all
        // fronts, continue with the first and so on, until enough individuals are selected.
        // XXX

        //let mut round = 0;
        'outer: while missing > 0 {
            for (_front_i, current_front) in fronts_grouped.iter_mut().enumerate() {
                // select up to `missing` solutions from current_front, but from each group only one
                // (which is choosen randomly).
                for objective_grp in current_front.iter_mut() {
                    'next_group: for (_grp_i, grp) in objective_grp.iter_mut().enumerate() {
                        if missing > 0 {
                            loop {
                                if grp.is_empty() {
                                    break;
                                }
                                //let i = if round == 0 && front_i == 0 && grp_i == 0 { // XXX?
                                // first round, first group and non-dominated front. Use always the best according
                                // to 0th objective.
                                let i = rng.gen_range(0, grp.len());
                                //} else {
                                // Select randomly
                                //rng.gen_range(0, grp.len())
                                //};
                                let idx = grp.swap_remove(i); // remove `i`th element from grp returning the solution index
                                if !solutions[idx].is_selected() {
                                    solutions[idx].select();
                                    missing -= 1;
                                    break;
                                }
                            }
                        } else {
                            break 'outer;
                        }
                    }
                }

                // only retain groups which are non-empty
                current_front.retain(|grp| grp.len() > 0);
            }
            //round += 1;
        }
    }
}

/// Select the best individual out of `k` randomly choosen.
/// This gives individuals with better fitness a higher chance to reproduce.
/// `n` is the total number of individuals.
///
/// NOTE: We are not using `sample(rng, 0..n, k)` as it is *very* expensive.
/// Instead we call `rng.gen_range()` k-times. The drawn items could be the same,
/// but the probability is very low if `n` is high compared to `k`.
#[inline]
pub fn tournament_selection_fast<R: Rng, F>(
    rng: &mut R,
    better_than: F,
    n: usize,
    k: usize,
) -> usize
where
    F: Fn(usize, usize) -> bool,
{
    assert!(n > 0);
    assert!(k > 0);
    assert!(n >= k);

    let mut best: usize = rng.gen_range(0, n);

    for _ in 1..k {
        let i = rng.gen_range(0, n);
        if better_than(i, best) {
            best = i;
        }
    }

    return best;
}
<|endoftext|>


<commit_before>use std::slice;

use crate::{Document, Node};

/// An `Iterator` that visits the joints of a `Skin`.
#[derive(Clone, Debug)]
pub struct Joints<'a> {
    /// The parent `Document` struct.
    pub(crate) document: &'a Document,

    /// The internal node index iterator.
    pub(crate) iter: slice::Iter<'a, json::Index<json::scene::Node>>,
}

impl<'a> Iterator for Joints<'a>  {
    type Item = Node<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter
            .next()
            .map(|index| self.document.nodes().nth(index.value()).unwrap())
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
    fn count(self) -> usize {
        self.iter.count()
    }
    fn last(self) -> Option<Self::Item> {
        let document = self.document;
        self.iter.last().map(|index| document.nodes().nth(index.value()).unwrap())
    }
    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.iter.nth(n).map(|index| self.document.nodes().nth(index.value()).unwrap())
    }
}
<commit_msg>Impl ExactSizeIterator for Joints<commit_after>use std::slice;

use crate::{Document, Node};

/// An `Iterator` that visits the joints of a `Skin`.
#[derive(Clone, Debug)]
pub struct Joints<'a> {
    /// The parent `Document` struct.
    pub(crate) document: &'a Document,

    /// The internal node index iterator.
    pub(crate) iter: slice::Iter<'a, json::Index<json::scene::Node>>,
}

impl<'a> ExactSizeIterator for Joints<'a> {}
impl<'a> Iterator for Joints<'a> {
    type Item = Node<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter
            .next()
            .map(|index| self.document.nodes().nth(index.value()).unwrap())
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
    fn count(self) -> usize {
        self.iter.count()
    }
    fn last(self) -> Option<Self::Item> {
        let document = self.document;
        self.iter
            .last()
            .map(|index| document.nodes().nth(index.value()).unwrap())
    }
    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.iter
            .nth(n)
            .map(|index| self.document.nodes().nth(index.value()).unwrap())
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![warn(dead_code)]

//! A user friendly game engine written in Rust.

#[cfg(feature = "include_gfx")]
extern crate libc;
#[cfg(feature = "include_gfx")]
extern crate gfx;
#[cfg(feature = "include_gfx")]
extern crate gfx_graphics;
extern crate opengl_graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;
extern crate graphics;
extern crate fps_counter;
extern crate current;
extern crate shader_version;

extern crate piston;

#[cfg(feature = "include_sdl2")]
pub use sdl2_window::Sdl2Window as WindowBackEnd;
#[cfg(feature = "include_glfw")]
pub use glfw_window::GlfwWindow as WindowBackEnd;
#[cfg(feature = "include_glutin")]
pub use glutin_window::GlutinWindow as WindowBackEnd;

#[cfg(feature = "include_gfx")]
use gfx_graphics::G2D;
#[cfg(feature = "include_gfx")]
use gfx::{ DeviceHelper };
use opengl_graphics::Gl;
use fps_counter::FPSCounter;

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;

use piston::window::WindowSettings;
use piston::quack::{ Get, Set };
use current::{ Current, CurrentGuard };

fn start_window<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    let mut window = Rc::new(RefCell::new(WindowBackEnd::new(
        opengl,
        window_settings,
    )));
    let mut gl = Rc::new(RefCell::new(Gl::new(opengl)));
    let mut fps_counter = Rc::new(RefCell::new(FPSCounter::new()));

    #[cfg(feature = "include_sdl2")]
    fn disable_vsync() { sdl2::video::gl_set_swap_interval(0); }

    #[cfg(not(feature = "include_sdl2"))]
    fn disable_vsync() {}

    disable_vsync();

    let window_guard = CurrentGuard::new(&mut window);
    let gl_guard = CurrentGuard::new(&mut gl);
    let fps_counter_guard = CurrentGuard::new(&mut fps_counter);

    f();

    drop(window_guard);
    drop(gl_guard);
    drop(fps_counter_guard);
}

#[cfg(feature = "include_gfx")]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    let window = current_window();

    let mut device = Rc::new(RefCell::new(gfx::GlDevice::new(|s| {
        #[cfg(feature = "include_sdl2")]
        fn get_proc_address(_: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            unsafe { std::mem::transmute(sdl2::video::gl_get_proc_address(s)) }
        }

        #[cfg(feature = "include_glfw")]
        fn get_proc_address(window: &mut WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        #[cfg(feature = "include_glutin")]
        fn get_proc_address(window: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        get_proc_address(&mut *window.borrow_mut(), s)
    })));
    let mut g2d = Rc::new(RefCell::new(G2D::new(&mut *device.borrow_mut())));
    let mut renderer = Rc::new(RefCell::new(device.borrow_mut().create_renderer()));
    let piston::window::Size([w, h]) = window.get();
    let mut frame = Rc::new(RefCell::new(gfx::Frame::new(w as u16, h as u16)));

    let device_guard = CurrentGuard::new(&mut device);
    let g2d_guard = CurrentGuard::new(&mut g2d);
    let renderer_guard = CurrentGuard::new(&mut renderer);
    let frame_guard = CurrentGuard::new(&mut frame);

    f();

    drop(g2d_guard);
    drop(renderer_guard);
    drop(frame_guard);
    drop(device_guard);
}

#[cfg(not(feature = "include_gfx"))]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    f();
}

/// Initializes window and sets up current objects.
pub fn start<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    start_window(opengl, window_settings, || {
        if cfg!(feature = "include_gfx") {
            start_gfx(|| f());
        } else {
            f();
        }
    });
}

/// The current window
pub fn current_window() -> Rc<RefCell<WindowBackEnd>> {
    unsafe {
        Current::<Rc<RefCell<WindowBackEnd>>>::new().clone()
    }
}
/// The current Gfx device
#[cfg(feature = "include_gfx")]
pub fn current_gfx_device() -> Rc<RefCell<gfx::GlDevice>> {
    unsafe {
        Current::<Rc<RefCell<gfx::GlDevice>>>::new().clone()
    }
}
/// The current opengl_graphics back-end
pub fn current_gl() -> Rc<RefCell<Gl>> {
    unsafe {
        Current::<Rc<RefCell<Gl>>>::new().clone()
    }
}
/// The current gfx_graphics back-end
#[cfg(feature = "include_gfx")]
pub fn current_g2d() -> Rc<RefCell<G2D>> {
    unsafe {
        Current::<Rc<RefCell<G2D>>>::new().clone()
    }
}
/// The current Gfx renderer
#[cfg(feature = "include_gfx")]
pub fn current_renderer() -> Rc<RefCell<gfx::Renderer<gfx::GlCommandBuffer>>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Renderer<gfx::GlCommandBuffer>>>>::new().clone()
    }
}
/// The current Gfx frame
#[cfg(feature = "include_gfx")]
pub fn current_frame() -> Rc<RefCell<gfx::Frame>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Frame>>>::new().clone()
    }
}
/// The current FPS counter
pub fn current_fps_counter() -> Rc<RefCell<FPSCounter>> {
    unsafe {
        Current::<Rc<RefCell<FPSCounter>>>::new().clone()
    }
}

/// Returns an event iterator for the event loop
pub fn events() -> piston::event::Events<
    Rc<RefCell<WindowBackEnd>>, piston::input::Input, piston::event::Event
> {
    piston::event::events(current_window())
}

/// Updates the FPS counter and gets the frames per second.
pub fn fps_tick() -> usize {
    current_fps_counter().borrow_mut().tick()
}

/// Sets title of the current window.
pub fn set_title(text: String) {
    current_window().set_mut(piston::window::Title(text));
}

/// Returns true if the current window should be closed.
pub fn should_close() -> bool {
    use piston::window::ShouldClose;
    let ShouldClose(val) = current_window().get();
    val
}

/// Renders 2D graphics using Gfx.
#[cfg(feature = "include_gfx")]
pub fn render_2d_gfx<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context,
            &mut gfx_graphics::GraphicsBackEnd<gfx::GlCommandBuffer>)
{
    use gfx::Device;

    let renderer = current_renderer();
    let mut renderer = renderer.borrow_mut();
    let renderer = &mut *renderer;
    current_g2d().borrow_mut().draw(
        renderer,
        &mut *current_frame().borrow_mut(),
        |c, g| {
            if let Some(bg_color) = bg_color {
                graphics::clear(bg_color, g);
            }
            f(c, g);
        });
    current_gfx_device().borrow_mut().submit(renderer.as_buffer());
    renderer.reset();
}

/// Renders 2D graphics using OpenGL.
///
/// Panics if called nested within the closure
/// to prevent mutable aliases to the graphics back-end.
pub fn render_2d_opengl<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context, &mut opengl_graphics::Gl)
{
    use std::ops::Deref;

    let piston::window::Size([w, h]) = current_window().borrow().deref().get();
    current_gl().borrow_mut().draw([0, 0, w as i32, h as i32], |c, g| {
        use graphics::*;
        if let Some(bg_color) = bg_color {
            graphics::clear(bg_color, g);
        }
        f(c, g);
    });
}

<commit_msg>Upgrade to latest Gfx/Rust<commit_after>#![deny(missing_docs)]
#![warn(dead_code)]

//! A user friendly game engine written in Rust.

#[cfg(feature = "include_gfx")]
extern crate libc;
#[cfg(feature = "include_gfx")]
extern crate gfx;
#[cfg(feature = "include_gfx")]
extern crate gfx_graphics;
extern crate opengl_graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;
extern crate graphics;
extern crate fps_counter;
extern crate current;
extern crate shader_version;

extern crate piston;

#[cfg(feature = "include_sdl2")]
pub use sdl2_window::Sdl2Window as WindowBackEnd;
#[cfg(feature = "include_glfw")]
pub use glfw_window::GlfwWindow as WindowBackEnd;
#[cfg(feature = "include_glutin")]
pub use glutin_window::GlutinWindow as WindowBackEnd;

#[cfg(feature = "include_gfx")]
use gfx_graphics::G2D;
#[cfg(feature = "include_gfx")]
use gfx::{ DeviceExt };
use opengl_graphics::Gl;
use fps_counter::FPSCounter;

use std::rc::Rc;
use std::cell::RefCell;

use piston::window::WindowSettings;
use piston::quack::{ Get, Set };
use current::{ Current, CurrentGuard };

fn start_window<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    let mut window = Rc::new(RefCell::new(WindowBackEnd::new(
        opengl,
        window_settings,
    )));
    let mut gl = Rc::new(RefCell::new(Gl::new(opengl)));
    let mut fps_counter = Rc::new(RefCell::new(FPSCounter::new()));

    #[cfg(feature = "include_sdl2")]
    fn disable_vsync() { sdl2::video::gl_set_swap_interval(0); }

    #[cfg(not(feature = "include_sdl2"))]
    fn disable_vsync() {}

    disable_vsync();

    let window_guard = CurrentGuard::new(&mut window);
    let gl_guard = CurrentGuard::new(&mut gl);
    let fps_counter_guard = CurrentGuard::new(&mut fps_counter);

    f();

    drop(window_guard);
    drop(gl_guard);
    drop(fps_counter_guard);
}

#[cfg(feature = "include_gfx")]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    let window = current_window();

    let mut device = Rc::new(RefCell::new(gfx::GlDevice::new(|s| {
        #[cfg(feature = "include_sdl2")]
        fn get_proc_address(_: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            unsafe { std::mem::transmute(sdl2::video::gl_get_proc_address(s)) }
        }

        #[cfg(feature = "include_glfw")]
        fn get_proc_address(window: &mut WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        #[cfg(feature = "include_glutin")]
        fn get_proc_address(window: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        get_proc_address(&mut *window.borrow_mut(), s)
    })));
    let mut g2d = Rc::new(RefCell::new(G2D::new(&mut *device.borrow_mut())));
    let mut renderer = Rc::new(RefCell::new(device.borrow_mut().create_renderer()));
    let piston::window::Size([w, h]) = window.get();
    let mut frame = Rc::new(RefCell::new(gfx::Frame::new(w as u16, h as u16)));

    let device_guard = CurrentGuard::new(&mut device);
    let g2d_guard = CurrentGuard::new(&mut g2d);
    let renderer_guard = CurrentGuard::new(&mut renderer);
    let frame_guard = CurrentGuard::new(&mut frame);

    f();

    drop(g2d_guard);
    drop(renderer_guard);
    drop(frame_guard);
    drop(device_guard);
}

#[cfg(not(feature = "include_gfx"))]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    f();
}

/// Initializes window and sets up current objects.
pub fn start<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    start_window(opengl, window_settings, || {
        if cfg!(feature = "include_gfx") {
            start_gfx(|| f());
        } else {
            f();
        }
    });
}

/// The current window
pub fn current_window() -> Rc<RefCell<WindowBackEnd>> {
    unsafe {
        Current::<Rc<RefCell<WindowBackEnd>>>::new().clone()
    }
}
/// The current Gfx device
#[cfg(feature = "include_gfx")]
pub fn current_gfx_device() -> Rc<RefCell<gfx::GlDevice>> {
    unsafe {
        Current::<Rc<RefCell<gfx::GlDevice>>>::new().clone()
    }
}
/// The current opengl_graphics back-end
pub fn current_gl() -> Rc<RefCell<Gl>> {
    unsafe {
        Current::<Rc<RefCell<Gl>>>::new().clone()
    }
}
/// The current gfx_graphics back-end
#[cfg(feature = "include_gfx")]
pub fn current_g2d() -> Rc<RefCell<G2D>> {
    unsafe {
        Current::<Rc<RefCell<G2D>>>::new().clone()
    }
}
/// The current Gfx renderer
#[cfg(feature = "include_gfx")]
pub fn current_renderer() -> Rc<RefCell<gfx::Renderer<gfx::GlDevice>>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Renderer<gfx::GlDevice>>>>::new().clone()
    }
}
/// The current Gfx frame
#[cfg(feature = "include_gfx")]
pub fn current_frame() -> Rc<RefCell<gfx::Frame>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Frame>>>::new().clone()
    }
}
/// The current FPS counter
pub fn current_fps_counter() -> Rc<RefCell<FPSCounter>> {
    unsafe {
        Current::<Rc<RefCell<FPSCounter>>>::new().clone()
    }
}

/// Returns an event iterator for the event loop
pub fn events() -> piston::event::Events<
    Rc<RefCell<WindowBackEnd>>, piston::input::Input, piston::event::Event
> {
    piston::event::events(current_window())
}

/// Updates the FPS counter and gets the frames per second.
pub fn fps_tick() -> usize {
    let fps_counter = current_fps_counter();
    let mut fps_counter = fps_counter.borrow_mut();
    fps_counter.tick()
}

/// Sets title of the current window.
pub fn set_title(text: String) {
    current_window().set_mut(piston::window::Title(text));
}

/// Returns true if the current window should be closed.
pub fn should_close() -> bool {
    use piston::window::ShouldClose;
    let ShouldClose(val) = current_window().get();
    val
}

/// Renders 2D graphics using Gfx.
#[cfg(feature = "include_gfx")]
pub fn render_2d_gfx<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context,
            &mut gfx_graphics::GraphicsBackEnd<gfx::GlDevice>)
{
    use gfx::Device;

    let renderer = current_renderer();
    let mut renderer = renderer.borrow_mut();
    let renderer = &mut *renderer;
    let g2d = current_g2d();
    let mut g2d = g2d.borrow_mut();
    let frame = current_frame();
    let frame = frame.borrow();
    g2d.draw(
        renderer,
        &*frame,
        |c, g| {
            if let Some(bg_color) = bg_color {
                graphics::clear(bg_color, g);
            }
            f(c, g);
        });
    let gfx_device = current_gfx_device();
    let mut gfx_device = gfx_device.borrow_mut();
    gfx_device.submit(renderer.as_buffer());
    renderer.reset();
}

/// Renders 2D graphics using OpenGL.
///
/// Panics if called nested within the closure
/// to prevent mutable aliases to the graphics back-end.
pub fn render_2d_opengl<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context, &mut opengl_graphics::Gl)
{
    let window = current_window();
    let window = window.borrow();
    let piston::window::Size([w, h]) = window.get();
    let gl = current_gl();
    let mut gl = gl.borrow_mut();
    gl.draw([0, 0, w as i32, h as i32], |c, g| {
        use graphics::*;
        if let Some(bg_color) = bg_color {
            graphics::clear(bg_color, g);
        }
        f(c, g);
    });
}

<|endoftext|>