<commit_before>use std::collections::VecDeque;

use parse::IrcMsg;
use event::IrcEvent;

pub trait MessageWatcher {
    fn on_irc_msg(&mut self, message: &IrcMsg);

    /// If true, the `MessageWatcher` should be removed from the watcher set
    fn finished(&self) -> bool;
}

pub trait EventWatcher {
    fn on_event(&mut self, message: &IrcEvent);

    /// If true, the `EventWatcher` should be removed from the watcher set
    fn is_finished(&self) -> bool;

    fn get_name(&self) -> &'static str;

    fn display(&self) -> String;
}

/// Emits IrcEvents when certain messages are detected
pub trait Bundler {
    fn on_irc_msg(&mut self, message: &IrcMsg) -> Vec<IrcEvent>;

    /// If true, the `Bundler` should be removed from the bundler set
    fn is_finished(&mut self) -> bool;

    fn get_name(&self) -> &'static str;
}

/// Emits Bundlers when certain messages are detected
pub trait BundlerTrigger {
    fn on_irc_msg(&mut self, message: &IrcMsg) -> Vec<Box<Bundler+Send+'static>>;
}

/// Controls the lifecycle of EventWatchers, Bundlers, and BundlerTriggers
pub struct BundlerManager {
    /// Unfinished watchers currently attached to the stream
    event_watchers: VecDeque<Box<EventWatcher+Send+'static>>,

    /// Active event bundlers.
    event_bundlers: VecDeque<Box<Bundler+Send+'static>>,

    /// Bundler triggers.  They create Bundlers.
    bundler_triggers: Vec<Box<BundlerTrigger+Send+'static>>,
}

impl BundlerManager {
    pub fn new() -> BundlerManager {
        BundlerManager {
            event_watchers: VecDeque::new(),
            event_bundlers: VecDeque::new(),
            bundler_triggers: Vec::new(),
        }
    }

    // Do we really need +Send here?
    pub fn add_watcher(&mut self, watcher: Box<EventWatcher+Send+'static>) {
        self.event_watchers.push_back(watcher);
    }

    pub fn add_bundler(&mut self, bundler: Box<Bundler+Send+'static>) {
        self.event_bundlers.push_back(bundler);
    }

    pub fn add_bundler_trigger(&mut self, bundler: Box<BundlerTrigger+Send+'static>) {
        self.bundler_triggers.push(bundler);
    }

    pub fn on_irc_msg(&mut self, msg: &IrcMsg) -> Vec<IrcEvent> {
        let mut outgoing_events: Vec<IrcEvent> = Vec::new();

        for new_bundler in bundler_trigger_impl(&mut self.bundler_triggers, msg).into_iter() {
            self.event_bundlers.push_back(new_bundler);
        }

        for event in bundler_accept_impl(&mut self.event_bundlers, msg).into_iter() {
            outgoing_events.push(event);
        }

        outgoing_events.push(IrcEvent::IrcMsg(msg.clone()));

        for event in outgoing_events.iter() {
            for watcher in watcher_accept_impl(&mut self.event_watchers, event).into_iter() {
                drop(watcher);
            }
        }

        outgoing_events
    }
}

fn bundler_trigger_impl(triggers: &mut Vec<Box<BundlerTrigger+Send+'static>>,
                        msg: &IrcMsg
                       ) -> Vec<Box<Bundler+Send>> {

    let mut activating: Vec<Box<Bundler+Send>> = Vec::new();
    for trigger in triggers.iter_mut() {
        let new_bundlers = trigger.on_irc_msg(msg);
        activating.reserve(new_bundlers.len());
        for bundler in new_bundlers.into_iter() {
            activating.push(bundler);
        }
    }
    activating
}

fn watcher_accept_impl(buf: &mut VecDeque<Box<EventWatcher+Send+'static>>,
                       event: &IrcEvent
                      ) -> Vec<Box<EventWatcher+Send+'static>> {
    let mut keep_watchers: VecDeque<Box<EventWatcher+Send>> = VecDeque::new();
    let mut finished_watchers: Vec<Box<EventWatcher+Send>> = Vec::new();

    loop {
        match buf.pop_front() {
            Some(mut watcher) => {
                watcher.on_event(event);
                if watcher.is_finished() {
                    finished_watchers.push(watcher);
                } else {
                    keep_watchers.push_back(watcher);
                }
            },
            None => break
        }
    }
    loop {
        match keep_watchers.pop_front() {
            Some(watcher) => buf.push_back(watcher),
            None => break
        }
    }
    finished_watchers
}

fn bundler_accept_impl(buf: &mut VecDeque<Box<Bundler+Send+'static>>,
                       msg: &IrcMsg
                      ) -> Vec<IrcEvent> {

    let mut keep_bundlers: VecDeque<Box<Bundler+Send>> = VecDeque::new();
    let mut emit_events: Vec<IrcEvent> = Vec::new();

    loop {
        match buf.pop_front() {
            Some(mut bundler) => {
                for event in bundler.on_irc_msg(msg).into_iter() {
                    emit_events.push(event);
                }
                if !bundler.is_finished() {
                    keep_bundlers.push_back(bundler);
                }
            },
            None => break
        }
    }
    loop {
        match keep_bundlers.pop_front() {
            Some(watcher) => buf.push_back(watcher),
            None => break
        }
    }
    emit_events
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::old_io::{IoResult, BufReader};

    use parse::IrcMsg;
    use watchers::{
        WhoBundlerTrigger,
        JoinBundlerTrigger,
    };
    use event::IrcEvent::{
        JoinBundle,
        WhoBundle,
    };

    const TEST_DATA: &'static [u8] = include_bytes!("../../testdata/watcher.txt");

    fn unsafe_to_irc_message(line_res: IoResult<String>) -> IrcMsg {
        let line = match line_res {
            Ok(line) => line,
            Err(err) => panic!("err: {:?}", err)
        };
        let totrim: &[_] = &['\n', '\r'];
        match IrcMsg::new(line.as_slice().trim_right_matches(totrim).to_string().into_bytes()) {
            Ok(message) => message,
            Err(err) => panic!("err: {:?}", err)
        }
    }

    #[test]
    fn test_bundle_watcher() {
        let mut reader = BufReader::new(TEST_DATA);
        let mut bunman = BundlerManager::new();
        bunman.add_bundler_trigger(Box::new(JoinBundlerTrigger::new()));
        bunman.add_bundler_trigger(Box::new(WhoBundlerTrigger::new()));
        let mut events = Vec::new();

        for msg in reader.lines().map(unsafe_to_irc_message) {
            events.extend(bunman.on_irc_msg(&msg).into_iter());
        }

        let mut join_bundles = 0;
        let mut who_bundles = 0;

        for event in events.into_iter() {
            if let JoinBundle(_) = event {
                join_bundles += 1;
            }
            if let WhoBundle(_) = event {
                who_bundles += 1
            }
        }
        assert_eq!(join_bundles, 1);
        assert_eq!(who_bundles, 1);
    }
}
<commit_msg>Add default constructor on BundlerManager<commit_after>use std::collections::VecDeque;

use parse::IrcMsg;
use event::IrcEvent;

pub trait MessageWatcher {
    fn on_irc_msg(&mut self, message: &IrcMsg);

    /// If true, the `MessageWatcher` should be removed from the watcher set
    fn finished(&self) -> bool;
}

pub trait EventWatcher {
    fn on_event(&mut self, message: &IrcEvent);

    /// If true, the `EventWatcher` should be removed from the watcher set
    fn is_finished(&self) -> bool;

    fn get_name(&self) -> &'static str;

    fn display(&self) -> String;
}

/// Emits IrcEvents when certain messages are detected
pub trait Bundler {
    fn on_irc_msg(&mut self, message: &IrcMsg) -> Vec<IrcEvent>;

    /// If true, the `Bundler` should be removed from the bundler set
    fn is_finished(&mut self) -> bool;

    fn get_name(&self) -> &'static str;
}

/// Emits Bundlers when certain messages are detected
pub trait BundlerTrigger {
    fn on_irc_msg(&mut self, message: &IrcMsg) -> Vec<Box<Bundler+Send+'static>>;
}

/// Controls the lifecycle of EventWatchers, Bundlers, and BundlerTriggers
pub struct BundlerManager {
    /// Unfinished watchers currently attached to the stream
    event_watchers: VecDeque<Box<EventWatcher+Send+'static>>,

    /// Active event bundlers.
    event_bundlers: VecDeque<Box<Bundler+Send+'static>>,

    /// Bundler triggers.  They create Bundlers.
    bundler_triggers: Vec<Box<BundlerTrigger+Send+'static>>,
}

impl BundlerManager {
    pub fn new() -> BundlerManager {
        BundlerManager {
            event_watchers: VecDeque::new(),
            event_bundlers: VecDeque::new(),
            bundler_triggers: Vec::new(),
        }
    }

    /// Initialise a BundlerManager with JoinBundlerTrigger and
    /// WhoBundlerTrigger
    pub fn with_defaults() -> BundlerManager {
        let mut manager = BundlerManager::new();
        manager.add_bundler_trigger(Box::new(super::JoinBundlerTrigger::new()));
        manager.add_bundler_trigger(Box::new(super::WhoBundlerTrigger::new()));
        manager
    }

    // Do we really need +Send here?
    pub fn add_watcher(&mut self, watcher: Box<EventWatcher+Send+'static>) {
        self.event_watchers.push_back(watcher);
    }

    pub fn add_bundler(&mut self, bundler: Box<Bundler+Send+'static>) {
        self.event_bundlers.push_back(bundler);
    }

    pub fn add_bundler_trigger(&mut self, bundler: Box<BundlerTrigger+Send+'static>) {
        self.bundler_triggers.push(bundler);
    }

    pub fn on_irc_msg(&mut self, msg: &IrcMsg) -> Vec<IrcEvent> {
        let mut outgoing_events: Vec<IrcEvent> = Vec::new();

        for new_bundler in bundler_trigger_impl(&mut self.bundler_triggers, msg).into_iter() {
            self.event_bundlers.push_back(new_bundler);
        }

        for event in bundler_accept_impl(&mut self.event_bundlers, msg).into_iter() {
            outgoing_events.push(event);
        }

        outgoing_events.push(IrcEvent::IrcMsg(msg.clone()));

        for event in outgoing_events.iter() {
            for watcher in watcher_accept_impl(&mut self.event_watchers, event).into_iter() {
                drop(watcher);
            }
        }

        outgoing_events
    }
}

fn bundler_trigger_impl(triggers: &mut Vec<Box<BundlerTrigger+Send+'static>>,
                        msg: &IrcMsg
                       ) -> Vec<Box<Bundler+Send>> {

    let mut activating: Vec<Box<Bundler+Send>> = Vec::new();
    for trigger in triggers.iter_mut() {
        let new_bundlers = trigger.on_irc_msg(msg);
        activating.reserve(new_bundlers.len());
        for bundler in new_bundlers.into_iter() {
            activating.push(bundler);
        }
    }
    activating
}

fn watcher_accept_impl(buf: &mut VecDeque<Box<EventWatcher+Send+'static>>,
                       event: &IrcEvent
                      ) -> Vec<Box<EventWatcher+Send+'static>> {
    let mut keep_watchers: VecDeque<Box<EventWatcher+Send>> = VecDeque::new();
    let mut finished_watchers: Vec<Box<EventWatcher+Send>> = Vec::new();

    loop {
        match buf.pop_front() {
            Some(mut watcher) => {
                watcher.on_event(event);
                if watcher.is_finished() {
                    finished_watchers.push(watcher);
                } else {
                    keep_watchers.push_back(watcher);
                }
            },
            None => break
        }
    }
    loop {
        match keep_watchers.pop_front() {
            Some(watcher) => buf.push_back(watcher),
            None => break
        }
    }
    finished_watchers
}

fn bundler_accept_impl(buf: &mut VecDeque<Box<Bundler+Send+'static>>,
                       msg: &IrcMsg
                      ) -> Vec<IrcEvent> {

    let mut keep_bundlers: VecDeque<Box<Bundler+Send>> = VecDeque::new();
    let mut emit_events: Vec<IrcEvent> = Vec::new();

    loop {
        match buf.pop_front() {
            Some(mut bundler) => {
                for event in bundler.on_irc_msg(msg).into_iter() {
                    emit_events.push(event);
                }
                if !bundler.is_finished() {
                    keep_bundlers.push_back(bundler);
                }
            },
            None => break
        }
    }
    loop {
        match keep_bundlers.pop_front() {
            Some(watcher) => buf.push_back(watcher),
            None => break
        }
    }
    emit_events
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::old_io::{IoResult, BufReader};

    use parse::IrcMsg;
    use watchers::{
        WhoBundlerTrigger,
        JoinBundlerTrigger,
    };
    use event::IrcEvent::{
        JoinBundle,
        WhoBundle,
    };

    const TEST_DATA: &'static [u8] = include_bytes!("../../testdata/watcher.txt");

    fn unsafe_to_irc_message(line_res: IoResult<String>) -> IrcMsg {
        let line = match line_res {
            Ok(line) => line,
            Err(err) => panic!("err: {:?}", err)
        };
        let totrim: &[_] = &['\n', '\r'];
        match IrcMsg::new(line.as_slice().trim_right_matches(totrim).to_string().into_bytes()) {
            Ok(message) => message,
            Err(err) => panic!("err: {:?}", err)
        }
    }

    #[test]
    fn test_bundle_watcher() {
        let mut reader = BufReader::new(TEST_DATA);
        let mut bunman = BundlerManager::new();
        bunman.add_bundler_trigger(Box::new(JoinBundlerTrigger::new()));
        bunman.add_bundler_trigger(Box::new(WhoBundlerTrigger::new()));
        let mut events = Vec::new();

        for msg in reader.lines().map(unsafe_to_irc_message) {
            events.extend(bunman.on_irc_msg(&msg).into_iter());
        }

        let mut join_bundles = 0;
        let mut who_bundles = 0;

        for event in events.into_iter() {
            if let JoinBundle(_) = event {
                join_bundles += 1;
            }
            if let WhoBundle(_) = event {
                who_bundles += 1
            }
        }
        assert_eq!(join_bundles, 1);
        assert_eq!(who_bundles, 1);
    }
}
<|endoftext|>


<commit_before>
use color::{Color, Colorable};
use elmesque::Element;
use frame::Frameable;
use graphics::character::CharacterCache;
use graphics::math::Scalar;
use label::{FontSize, Labelable};
use mouse::Mouse;
use position::{self, Depth, Dimensions, HorizontalAlign, Point, Position, VerticalAlign};
use theme::Theme;
use ui::{GlyphCache, UserInput};
use widget::{self, Widget, WidgetId};

/// A pressable widget for toggling the state of a bool. Like the button widget, it's reaction is
/// triggered upon release and will return the new bool state. Note that the toggle will not
/// mutate the bool for you, you should do this yourself within the react closure.
pub struct Toggle<'a, F> {
    pos: Position,
    maybe_h_align: Option<HorizontalAlign>,
    maybe_v_align: Option<VerticalAlign>,
    depth: Depth,
    value: bool,
    maybe_react: Option<F>,
    maybe_label: Option<&'a str>,
    style: Style,
    enabled: bool,
    maybe_parent_id: Option<WidgetId>,
}

/// Styling for the Toggle, necessary for constructing its renderable Element.
#[allow(missing_docs, missing_copy_implementations)]
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Style {
    pub maybe_width: Option<Scalar>,
    pub maybe_height: Option<Scalar>,
    pub maybe_color: Option<Color>,
    pub maybe_frame: Option<Scalar>,
    pub maybe_frame_color: Option<Color>,
    pub maybe_label_color: Option<Color>,
    pub maybe_label_font_size: Option<u32>,
}

/// The way in which the Toggle is being interacted with.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Interaction {
    Normal,
    Highlighted,
    Clicked,
}

/// The state of the Toggle.
#[derive(Clone, Debug, PartialEq)]
pub struct State {
    value: bool,
    interaction: Interaction,
    maybe_label: Option<String>,
}

impl State {
    /// Alter the widget color depending on the state.
    fn color(&self, color: Color) -> Color {
        match self.interaction {
            Interaction::Normal => color,
            Interaction::Highlighted => color.highlighted(),
            Interaction::Clicked => color.clicked(),
        }
    }
}

/// Check the current state of the button.
fn get_new_interaction(is_over: bool,
                       prev: Interaction,
                       mouse: Mouse) -> Interaction {
    use mouse::ButtonState::{Down, Up};
    use self::Interaction::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

impl<'a, F> Toggle<'a, F> {

    /// Construct a new Toggle widget.
    pub fn new(value: bool) -> Toggle<'a, F> {
        Toggle {
            pos: Position::default(),
            maybe_h_align: None,
            maybe_v_align: None,
            depth: 0.0,
            maybe_react: None,
            maybe_label: None,
            value: value,
            style: Style::new(),
            enabled: true,
            maybe_parent_id: None,
        }
    }

    /// Set the reaction for the Toggle. It will be triggered upon release of the button.
    pub fn react(mut self, reaction: F) -> Self {
        self.maybe_react = Some(reaction);
        self
    }

    /// If true, will allow user inputs.  If false, will disallow user inputs.
    pub fn enabled(mut self, flag: bool) -> Self {
        self.enabled = flag;
        self
    }

    /// Set which parent to attach the Widget to. Note that you can also attach a widget to a
    /// parent by using the placement `Positionable` methods.
    pub fn parent(mut self, id: WidgetId) -> Self {
        self.maybe_parent_id = Some(id);
        self
    }

}

impl<'a, F> Widget for Toggle<'a, F>
    where
        F: FnMut(bool),
{
    type State = State;
    type Style = Style;
    fn unique_kind(&self) -> &'static str { "Toggle" }
    fn init_state(&self) -> State {
        State {
            value: self.value,
            interaction: Interaction::Normal,
            maybe_label: None,
        }
    }
    fn style(&self) -> Style { self.style.clone() }
    fn parent_id(&self) -> Option<WidgetId> { self.maybe_parent_id }

    /// Update the state of the Toggle.
    fn update<'b, C>(mut self,
                     prev_state: &widget::State<State>,
                     xy: Point,
                     dim: Dimensions,
                     input: UserInput<'b>,
                     _style: &Style,
                     _theme: &Theme,
                     _glyph_cache: &GlyphCache<C>) -> Option<State>
        where
            C: CharacterCache,
    {
        use utils::is_over_rect;

        let widget::State { ref state, .. } = *prev_state;
        let maybe_mouse = input.maybe_mouse.map(|mouse| mouse.relative_to(xy));

        // Check whether or not a new interaction has occurred.
        let new_interaction = match (self.enabled, maybe_mouse) {
            (false, _) | (true, None) => Interaction::Normal,
            (true, Some(mouse)) => {
                let is_over = is_over_rect([0.0, 0.0], mouse.xy, dim);
                get_new_interaction(is_over, state.interaction, mouse)
            },
        };

        // React and determine the new value.
        let new_value = match (state.interaction, new_interaction) {
            (Interaction::Clicked, Interaction::Highlighted) => {
                let new_value = !self.value;
                if let Some(ref mut react) = self.maybe_react { react(!self.value) }
                new_value
            },
            _ => self.value,
        };

        // A function for constructing a new Toggle State.
        let new_state = || {
            State {
                maybe_label: self.maybe_label.as_ref().map(|label| label.to_string()),
                value: new_value,
                interaction: new_interaction,
            }
        };

        // Check whether or not the state has changed since the previous update.
        let state_has_changed = state.interaction != new_interaction
            || state.value != self.value
            || state.maybe_label.as_ref().map(|string| &string[..]) != self.maybe_label;

        // Construct the new state if there was a change.
        if state_has_changed { Some(new_state()) } else { None }
    }

    /// Construct an Element from the given Toggle State.
    fn draw<C>(new_state: &widget::State<State>,
               style: &Style,
               theme: &Theme,
               _glyph_cache: &GlyphCache<C>) -> Element
        where
            C: CharacterCache,
    {
        use elmesque::form::{collage, rect, text};

        let widget::State { ref state, dim, xy, .. } = *new_state;

        // Construct the frame and pressable forms.
        let frame = style.frame(theme);
        let frame_color = style.frame_color(theme);
        let (inner_w, inner_h) = (dim[0] - frame * 2.0, dim[1] - frame * 2.0);
        let frame_form = rect(dim[0], dim[1]).filled(frame_color);
        let color = style.color(theme);
        let color = state.color(if state.value { color }
                                    else { color.with_luminance(0.1) });
        let pressable_form = rect(inner_w, inner_h).filled(color);

        // Construct the label's Form.
        let maybe_label_form = state.maybe_label.as_ref().map(|label_text| {
            use elmesque::text::Text;
            let label_color = style.label_color(theme);
            let font_size = style.label_font_size(theme) as f64;
            text(Text::from_string(label_text.clone()).color(label_color).height(font_size))
                .shift(xy[0].floor(), xy[1].floor())
        });

        // Chain the Forms and shift them into position.
        let form_chain = Some(frame_form).into_iter()
            .chain(Some(pressable_form).into_iter())
            .map(|form| form.shift(xy[0], xy[1]))
            .chain(maybe_label_form.into_iter());

        // Collect the Forms into a renderable Element.
        collage(dim[0] as i32, dim[1] as i32, form_chain.collect())
    }

}

impl Style {

    /// Construct the default Style.
    pub fn new() -> Style {
        Style {
            maybe_width: None,
            maybe_height: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }

    /// Get the width of the Widget.
    pub fn width(&self, theme: &Theme) -> Scalar {
        const DEFAULT_WIDTH: Scalar = 64.0;
        self.maybe_width.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_width.unwrap_or(DEFAULT_WIDTH)
        })).unwrap_or(DEFAULT_WIDTH)
    }

    /// Get the height of the Widget.
    pub fn height(&self, theme: &Theme) -> Scalar {
        const DEFAULT_HEIGHT: Scalar = 64.0;
        self.maybe_height.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_height.unwrap_or(DEFAULT_HEIGHT)
        })).unwrap_or(DEFAULT_HEIGHT)
    }

    /// Get the Color for an Element.
    pub fn color(&self, theme: &Theme) -> Color {
        self.maybe_color.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_color.unwrap_or(theme.shape_color)
        })).unwrap_or(theme.shape_color)
    }

    /// Get the frame for an Element.
    pub fn frame(&self, theme: &Theme) -> f64 {
        self.maybe_frame.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_frame.unwrap_or(theme.frame_width)
        })).unwrap_or(theme.frame_width)
    }

    /// Get the frame Color for an Element.
    pub fn frame_color(&self, theme: &Theme) -> Color {
        self.maybe_frame_color.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_frame_color.unwrap_or(theme.frame_color)
        })).unwrap_or(theme.frame_color)
    }

    /// Get the label Color for an Element.
    pub fn label_color(&self, theme: &Theme) -> Color {
        self.maybe_label_color.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_label_color.unwrap_or(theme.label_color)
        })).unwrap_or(theme.label_color)
    }

    /// Get the label font size for an Element.
    pub fn label_font_size(&self, theme: &Theme) -> FontSize {
        self.maybe_label_font_size.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_label_font_size.unwrap_or(theme.font_size_medium)
        })).unwrap_or(theme.font_size_medium)
    }

}

impl<'a, F> Colorable for Toggle<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.style.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Toggle<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.style.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.style.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Labelable<'a> for Toggle<'a, F> {
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.style.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.style.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, F> position::Positionable for Toggle<'a, F> {
    fn position(mut self, pos: Position) -> Self {
        self.pos = pos;
        self
    }
    fn get_position(&self) -> Position { self.pos }
    #[inline]
    fn horizontal_align(self, h_align: HorizontalAlign) -> Self {
        Toggle { maybe_h_align: Some(h_align), ..self }
    }
    #[inline]
    fn vertical_align(self, v_align: VerticalAlign) -> Self {
        Toggle { maybe_v_align: Some(v_align), ..self }
    }
    fn get_horizontal_align(&self, theme: &Theme) -> HorizontalAlign {
        self.maybe_h_align.unwrap_or(theme.align.horizontal)
    }
    fn get_vertical_align(&self, theme: &Theme) -> VerticalAlign {
        self.maybe_v_align.unwrap_or(theme.align.vertical)
    }
    fn depth(mut self, depth: Depth) -> Self {
        self.depth = depth;
        self
    }
    fn get_depth(&self) -> Depth { self.depth }
}

impl<'a, F> position::Sizeable for Toggle<'a, F> {
    fn width(mut self, w: Scalar) -> Self {
        self.style.maybe_width = Some(w);
        self
    }
    fn height(mut self, h: Scalar) -> Self {
        self.style.maybe_height = Some(h);
        self
    }
    fn get_width<C: CharacterCache>(&self, theme: &Theme, _: &GlyphCache<C>) -> Scalar {
        self.style.width(theme)
    }
    fn get_height(&self, theme: &Theme) -> Scalar {
        self.style.height(theme)
    }
}

<commit_msg>Updated Toggle to new CommonBuilder changes<commit_after>
use color::{Color, Colorable};
use elmesque::Element;
use frame::Frameable;
use graphics::character::CharacterCache;
use graphics::math::Scalar;
use label::{FontSize, Labelable};
use mouse::Mouse;
use position::{self, Depth, Dimensions, HorizontalAlign, Point, Position, VerticalAlign};
use theme::Theme;
use ui::{GlyphCache, UserInput};
use widget::{self, Widget, WidgetId};

/// A pressable widget for toggling the state of a bool. Like the button widget, it's reaction is
/// triggered upon release and will return the new bool state. Note that the toggle will not
/// mutate the bool for you, you should do this yourself within the react closure.
pub struct Toggle<'a, F> {
    common: widget::CommonBuilder,
    value: bool,
    maybe_react: Option<F>,
    maybe_label: Option<&'a str>,
    style: Style,
    enabled: bool,
}

/// Styling for the Toggle, necessary for constructing its renderable Element.
#[allow(missing_docs, missing_copy_implementations)]
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Style {
    pub maybe_color: Option<Color>,
    pub maybe_frame: Option<Scalar>,
    pub maybe_frame_color: Option<Color>,
    pub maybe_label_color: Option<Color>,
    pub maybe_label_font_size: Option<u32>,
}

/// The way in which the Toggle is being interacted with.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Interaction {
    Normal,
    Highlighted,
    Clicked,
}

/// The state of the Toggle.
#[derive(Clone, Debug, PartialEq)]
pub struct State {
    value: bool,
    interaction: Interaction,
    maybe_label: Option<String>,
}

impl State {
    /// Alter the widget color depending on the state.
    fn color(&self, color: Color) -> Color {
        match self.interaction {
            Interaction::Normal => color,
            Interaction::Highlighted => color.highlighted(),
            Interaction::Clicked => color.clicked(),
        }
    }
}

/// Check the current state of the button.
fn get_new_interaction(is_over: bool,
                       prev: Interaction,
                       mouse: Mouse) -> Interaction {
    use mouse::ButtonState::{Down, Up};
    use self::Interaction::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

impl<'a, F> Toggle<'a, F> {

    /// Construct a new Toggle widget.
    pub fn new(value: bool) -> Toggle<'a, F> {
        Toggle {
            common: widget::CommonBuilder::new(),
            maybe_react: None,
            maybe_label: None,
            value: value,
            style: Style::new(),
            enabled: true,
        }
    }

    /// Set the reaction for the Toggle. It will be triggered upon release of the button.
    pub fn react(mut self, reaction: F) -> Self {
        self.maybe_react = Some(reaction);
        self
    }

    /// If true, will allow user inputs.  If false, will disallow user inputs.
    pub fn enabled(mut self, flag: bool) -> Self {
        self.enabled = flag;
        self
    }

}

impl<'a, F> Widget for Toggle<'a, F>
    where
        F: FnMut(bool),
{
    type State = State;
    type Style = Style;
    fn common(&self) -> &CommonBuilder { &self.common }
    fn common_mut(&mut self) -> &mut CommonBuilder { &mut self.common }
    fn unique_kind(&self) -> &'static str { "Toggle" }
    fn init_state(&self) -> State {
        State {
            value: self.value,
            interaction: Interaction::Normal,
            maybe_label: None,
        }
    }
    fn style(&self) -> Style { self.style.clone() }

    fn default_width(&self, theme: &Theme) -> Scalar {
        const DEFAULT_WIDTH: Scalar = 64.0;
        self.maybe_width.or(theme.maybe_toggle.as_ref().map(|default| {
            default.common.maybe_width.unwrap_or(DEFAULT_WIDTH)
        })).unwrap_or(DEFAULT_WIDTH)
    }

    fn default_height(&self, theme: &Theme) -> Scalar {
        const DEFAULT_HEIGHT: Scalar = 64.0;
        self.maybe_height.or(theme.maybe_toggle.as_ref().map(|default| {
            default.common.maybe_height.unwrap_or(DEFAULT_HEIGHT)
        })).unwrap_or(DEFAULT_HEIGHT)
    }

    /// Update the state of the Toggle.
    fn update<'b, C>(mut self,
                     prev_state: &widget::State<State>,
                     xy: Point,
                     dim: Dimensions,
                     input: UserInput<'b>,
                     _style: &Style,
                     _theme: &Theme,
                     _glyph_cache: &GlyphCache<C>) -> Option<State>
        where
            C: CharacterCache,
    {
        use utils::is_over_rect;

        let widget::State { ref state, .. } = *prev_state;
        let maybe_mouse = input.maybe_mouse.map(|mouse| mouse.relative_to(xy));

        // Check whether or not a new interaction has occurred.
        let new_interaction = match (self.enabled, maybe_mouse) {
            (false, _) | (true, None) => Interaction::Normal,
            (true, Some(mouse)) => {
                let is_over = is_over_rect([0.0, 0.0], mouse.xy, dim);
                get_new_interaction(is_over, state.interaction, mouse)
            },
        };

        // React and determine the new value.
        let new_value = match (state.interaction, new_interaction) {
            (Interaction::Clicked, Interaction::Highlighted) => {
                let new_value = !self.value;
                if let Some(ref mut react) = self.maybe_react { react(!self.value) }
                new_value
            },
            _ => self.value,
        };

        // A function for constructing a new Toggle State.
        let new_state = || {
            State {
                maybe_label: self.maybe_label.as_ref().map(|label| label.to_string()),
                value: new_value,
                interaction: new_interaction,
            }
        };

        // Check whether or not the state has changed since the previous update.
        let state_has_changed = state.interaction != new_interaction
            || state.value != self.value
            || state.maybe_label.as_ref().map(|string| &string[..]) != self.maybe_label;

        // Construct the new state if there was a change.
        if state_has_changed { Some(new_state()) } else { None }
    }

    /// Construct an Element from the given Toggle State.
    fn draw<C>(new_state: &widget::State<State>,
               style: &Style,
               theme: &Theme,
               _glyph_cache: &GlyphCache<C>) -> Element
        where
            C: CharacterCache,
    {
        use elmesque::form::{collage, rect, text};

        let widget::State { ref state, dim, xy, .. } = *new_state;

        // Construct the frame and pressable forms.
        let frame = style.frame(theme);
        let frame_color = style.frame_color(theme);
        let (inner_w, inner_h) = (dim[0] - frame * 2.0, dim[1] - frame * 2.0);
        let frame_form = rect(dim[0], dim[1]).filled(frame_color);
        let color = style.color(theme);
        let color = state.color(if state.value { color }
                                    else { color.with_luminance(0.1) });
        let pressable_form = rect(inner_w, inner_h).filled(color);

        // Construct the label's Form.
        let maybe_label_form = state.maybe_label.as_ref().map(|label_text| {
            use elmesque::text::Text;
            let label_color = style.label_color(theme);
            let font_size = style.label_font_size(theme) as f64;
            text(Text::from_string(label_text.clone()).color(label_color).height(font_size))
                .shift(xy[0].floor(), xy[1].floor())
        });

        // Chain the Forms and shift them into position.
        let form_chain = Some(frame_form).into_iter()
            .chain(Some(pressable_form).into_iter())
            .map(|form| form.shift(xy[0], xy[1]))
            .chain(maybe_label_form.into_iter());

        // Collect the Forms into a renderable Element.
        collage(dim[0] as i32, dim[1] as i32, form_chain.collect())
    }

}

impl Style {

    /// Construct the default Style.
    pub fn new() -> Style {
        Style {
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }

    /// Get the Color for an Element.
    pub fn color(&self, theme: &Theme) -> Color {
        self.maybe_color.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_color.unwrap_or(theme.shape_color)
        })).unwrap_or(theme.shape_color)
    }

    /// Get the frame for an Element.
    pub fn frame(&self, theme: &Theme) -> f64 {
        self.maybe_frame.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_frame.unwrap_or(theme.frame_width)
        })).unwrap_or(theme.frame_width)
    }

    /// Get the frame Color for an Element.
    pub fn frame_color(&self, theme: &Theme) -> Color {
        self.maybe_frame_color.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_frame_color.unwrap_or(theme.frame_color)
        })).unwrap_or(theme.frame_color)
    }

    /// Get the label Color for an Element.
    pub fn label_color(&self, theme: &Theme) -> Color {
        self.maybe_label_color.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_label_color.unwrap_or(theme.label_color)
        })).unwrap_or(theme.label_color)
    }

    /// Get the label font size for an Element.
    pub fn label_font_size(&self, theme: &Theme) -> FontSize {
        self.maybe_label_font_size.or(theme.maybe_toggle.as_ref().map(|style| {
            style.maybe_label_font_size.unwrap_or(theme.font_size_medium)
        })).unwrap_or(theme.font_size_medium)
    }

}

impl<'a, F> Colorable for Toggle<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.style.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Toggle<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.style.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.style.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Labelable<'a> for Toggle<'a, F> {
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.style.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.style.maybe_label_font_size = Some(size);
        self
    }
}

<|endoftext|>


<commit_before>//! This module is concerned with finding methods that a given type provides.
//! For details about how this works in rustc, see the method lookup page in the
//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
use std::sync::Arc;

use arrayvec::ArrayVec;
use rustc_hash::FxHashMap;

use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
use crate::{
    generics::HasGenericParams,
    impl_block::{ImplBlock, ImplId, ImplItem},
    nameres::CrateModuleId,
    resolve::Resolver,
    traits::TraitItem,
    ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy},
    ty::{traits::Solution, Ty, TypeCtor},
    Crate, Function, HirDatabase, Module, Name, Trait,
};

/// This is used as a key for indexing impls.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TyFingerprint {
    Apply(TypeCtor),
}

impl TyFingerprint {
    /// Creates a TyFingerprint for looking up an impl. Only certain types can
    /// have impls: if we have some `struct S`, we can have an `impl S`, but not
    /// `impl &S`. Hence, this will return `None` for reference types and such.
    fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
        match ty {
            Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
            _ => None,
        }
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct CrateImplBlocks {
    /// To make sense of the CrateModuleIds, we need the source root.
    krate: Crate,
    impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
    impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
}

impl CrateImplBlocks {
    pub fn lookup_impl_blocks<'a>(&'a self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + 'a {
        let fingerprint = TyFingerprint::for_impl(ty);
        fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map(
            move |(module_id, impl_id)| {
                let module = Module { krate: self.krate, module_id: *module_id };
                ImplBlock::from_id(module, *impl_id)
            },
        )
    }

    pub fn lookup_impl_blocks_for_trait<'a>(
        &'a self,
        tr: Trait,
    ) -> impl Iterator<Item = ImplBlock> + 'a {
        self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map(
            move |(module_id, impl_id)| {
                let module = Module { krate: self.krate, module_id: *module_id };
                ImplBlock::from_id(module, *impl_id)
            },
        )
    }

    fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
        let module_impl_blocks = db.impls_in_module(module);

        for (impl_id, _) in module_impl_blocks.impls.iter() {
            let impl_block = ImplBlock::from_id(module_impl_blocks.module, impl_id);

            let target_ty = impl_block.target_ty(db);

            if impl_block.target_trait(db).is_some() {
                if let Some(tr) = impl_block.target_trait_ref(db) {
                    self.impls_by_trait
                        .entry(tr.trait_)
                        .or_insert_with(Vec::new)
                        .push((module.module_id, impl_id));
                }
            } else {
                if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
                    self.impls
                        .entry(target_ty_fp)
                        .or_insert_with(Vec::new)
                        .push((module.module_id, impl_id));
                }
            }
        }

        for child in module.children(db) {
            self.collect_recursive(db, child);
        }
    }

    pub(crate) fn impls_in_crate_query(
        db: &impl HirDatabase,
        krate: Crate,
    ) -> Arc<CrateImplBlocks> {
        let mut crate_impl_blocks = CrateImplBlocks {
            krate,
            impls: FxHashMap::default(),
            impls_by_trait: FxHashMap::default(),
        };
        if let Some(module) = krate.root_module(db) {
            crate_impl_blocks.collect_recursive(db, module);
        }
        Arc::new(crate_impl_blocks)
    }
}

fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> {
    // Types like slice can have inherent impls in several crates, (core and alloc).
    // The corresponding impls are marked with lang items, so we can use them to find the required crates.
    macro_rules! lang_item_crate {
        ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{
            let mut v = ArrayVec::<[Crate; 2]>::new();
            $(
                v.push($db.lang_item($cur_crate, $name.into())?.krate($db)?);
            )+
            Some(v)
        }};
    }

    match ty {
        Ty::Apply(a_ty) => match a_ty.ctor {
            TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()),
            TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"),
            TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"),
            TypeCtor::Float(UncertainFloatTy::Known(f)) => match f.bitness {
                // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
                FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"),
                FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"),
            },
            TypeCtor::Int(UncertainIntTy::Known(i)) => {
                lang_item_crate!(db, cur_crate, i.ty_to_string())
            }
            TypeCtor::Str => lang_item_crate!(db, cur_crate, "str"),
            TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"),
            _ => None,
        },
        _ => None,
    }
}

/// Look up the method with the given name, returning the actual autoderefed
/// receiver type (but without autoref applied yet).
pub(crate) fn lookup_method(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    name: &Name,
    resolver: &Resolver,
) -> Option<(Ty, Function)> {
    iterate_method_candidates(ty, db, resolver, Some(name), |ty, f| Some((ty.clone(), f)))
}

// This would be nicer if it just returned an iterator, but that runs into
// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
pub(crate) fn iterate_method_candidates<T>(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    resolver: &Resolver,
    name: Option<&Name>,
    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
    // For method calls, rust first does any number of autoderef, and then one
    // autoref (i.e. when the method takes &self or &mut self). We just ignore
    // the autoref currently -- when we find a method matching the given name,
    // we assume it fits.

    // Also note that when we've got a receiver like &S, even if the method we
    // find in the end takes &self, we still do the autoderef step (just as
    // rustc does an autoderef and then autoref again).

    let krate = resolver.krate()?;
    for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
        if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback)
        {
            return Some(result);
        }
        if let Some(result) =
            iterate_trait_method_candidates(&derefed_ty, db, resolver, name, &mut callback)
        {
            return Some(result);
        }
    }
    None
}

fn iterate_trait_method_candidates<T>(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    resolver: &Resolver,
    name: Option<&Name>,
    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
    let krate = resolver.krate()?;
    // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
    let env = lower::trait_env(db, resolver);
    'traits: for t in resolver.traits_in_scope(db) {
        let data = t.trait_data(db);
        // we'll be lazy about checking whether the type implements the
        // trait, but if we find out it doesn't, we'll skip the rest of the
        // iteration
        let mut known_implemented = false;
        for item in data.items() {
            if let TraitItem::Function(m) = *item {
                let data = m.data(db);
                if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
                    if !known_implemented {
                        let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
                        if db.trait_solve(krate, goal).is_none() {
                            continue 'traits;
                        }
                    }
                    known_implemented = true;
                    if let Some(result) = callback(&ty.value, m) {
                        return Some(result);
                    }
                }
            }
        }
    }
    None
}

fn iterate_inherent_methods<T>(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    name: Option<&Name>,
    krate: Crate,
    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
    for krate in def_crates(db, krate, &ty.value)? {
        let impls = db.impls_in_crate(krate);

        for impl_block in impls.lookup_impl_blocks(&ty.value) {
            for item in impl_block.items(db) {
                if let ImplItem::Method(f) = item {
                    let data = f.data(db);
                    if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
                        if let Some(result) = callback(&ty.value, f) {
                            return Some(result);
                        }
                    }
                }
            }
        }
    }
    None
}

pub(crate) fn implements_trait(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    resolver: &Resolver,
    krate: Crate,
    trait_: Trait,
) -> bool {
    let env = lower::trait_env(db, resolver);
    let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
    let solution = db.trait_solve(krate, goal);

    solution.is_some()
}

impl Ty {
    // This would be nicer if it just returned an iterator, but that runs into
    // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
    pub fn iterate_impl_items<T>(
        self,
        db: &impl HirDatabase,
        krate: Crate,
        mut callback: impl FnMut(ImplItem) -> Option<T>,
    ) -> Option<T> {
        for krate in def_crates(db, krate, &self)? {
            let impls = db.impls_in_crate(krate);

            for impl_block in impls.lookup_impl_blocks(&self) {
                for item in impl_block.items(db) {
                    if let Some(result) = callback(item) {
                        return Some(result);
                    }
                }
            }
        }
        None
    }
}

/// This creates Substs for a trait with the given Self type and type variables
/// for all other parameters, to query Chalk with it.
fn generic_implements_goal(
    db: &impl HirDatabase,
    env: Arc<TraitEnvironment>,
    trait_: Trait,
    self_ty: Canonical<Ty>,
) -> Canonical<InEnvironment<super::Obligation>> {
    let mut substs = Vec::new();
    let generics = trait_.generic_params(db);
    let num_vars = self_ty.num_vars;
    substs.push(self_ty.value);
    substs.extend(
        generics
            .params_including_parent()
            .into_iter()
            .skip(1)
            .enumerate()
            .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
    );
    let num_vars = substs.len() - 1 + self_ty.num_vars;
    let trait_ref = TraitRef { trait_, substs: substs.into() };
    let obligation = super::Obligation::Trait(trait_ref);
    Canonical { num_vars, value: InEnvironment::new(env, obligation) }
}
<commit_msg>do fixup: remove unused import<commit_after>//! This module is concerned with finding methods that a given type provides.
//! For details about how this works in rustc, see the method lookup page in the
//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
use std::sync::Arc;

use arrayvec::ArrayVec;
use rustc_hash::FxHashMap;

use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
use crate::{
    generics::HasGenericParams,
    impl_block::{ImplBlock, ImplId, ImplItem},
    nameres::CrateModuleId,
    resolve::Resolver,
    traits::TraitItem,
    ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy},
    ty::{Ty, TypeCtor},
    Crate, Function, HirDatabase, Module, Name, Trait,
};

/// This is used as a key for indexing impls.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TyFingerprint {
    Apply(TypeCtor),
}

impl TyFingerprint {
    /// Creates a TyFingerprint for looking up an impl. Only certain types can
    /// have impls: if we have some `struct S`, we can have an `impl S`, but not
    /// `impl &S`. Hence, this will return `None` for reference types and such.
    fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
        match ty {
            Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
            _ => None,
        }
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct CrateImplBlocks {
    /// To make sense of the CrateModuleIds, we need the source root.
    krate: Crate,
    impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
    impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
}

impl CrateImplBlocks {
    pub fn lookup_impl_blocks<'a>(&'a self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + 'a {
        let fingerprint = TyFingerprint::for_impl(ty);
        fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map(
            move |(module_id, impl_id)| {
                let module = Module { krate: self.krate, module_id: *module_id };
                ImplBlock::from_id(module, *impl_id)
            },
        )
    }

    pub fn lookup_impl_blocks_for_trait<'a>(
        &'a self,
        tr: Trait,
    ) -> impl Iterator<Item = ImplBlock> + 'a {
        self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map(
            move |(module_id, impl_id)| {
                let module = Module { krate: self.krate, module_id: *module_id };
                ImplBlock::from_id(module, *impl_id)
            },
        )
    }

    fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
        let module_impl_blocks = db.impls_in_module(module);

        for (impl_id, _) in module_impl_blocks.impls.iter() {
            let impl_block = ImplBlock::from_id(module_impl_blocks.module, impl_id);

            let target_ty = impl_block.target_ty(db);

            if impl_block.target_trait(db).is_some() {
                if let Some(tr) = impl_block.target_trait_ref(db) {
                    self.impls_by_trait
                        .entry(tr.trait_)
                        .or_insert_with(Vec::new)
                        .push((module.module_id, impl_id));
                }
            } else {
                if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
                    self.impls
                        .entry(target_ty_fp)
                        .or_insert_with(Vec::new)
                        .push((module.module_id, impl_id));
                }
            }
        }

        for child in module.children(db) {
            self.collect_recursive(db, child);
        }
    }

    pub(crate) fn impls_in_crate_query(
        db: &impl HirDatabase,
        krate: Crate,
    ) -> Arc<CrateImplBlocks> {
        let mut crate_impl_blocks = CrateImplBlocks {
            krate,
            impls: FxHashMap::default(),
            impls_by_trait: FxHashMap::default(),
        };
        if let Some(module) = krate.root_module(db) {
            crate_impl_blocks.collect_recursive(db, module);
        }
        Arc::new(crate_impl_blocks)
    }
}

fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> {
    // Types like slice can have inherent impls in several crates, (core and alloc).
    // The corresponding impls are marked with lang items, so we can use them to find the required crates.
    macro_rules! lang_item_crate {
        ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{
            let mut v = ArrayVec::<[Crate; 2]>::new();
            $(
                v.push($db.lang_item($cur_crate, $name.into())?.krate($db)?);
            )+
            Some(v)
        }};
    }

    match ty {
        Ty::Apply(a_ty) => match a_ty.ctor {
            TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()),
            TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"),
            TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"),
            TypeCtor::Float(UncertainFloatTy::Known(f)) => match f.bitness {
                // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
                FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"),
                FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"),
            },
            TypeCtor::Int(UncertainIntTy::Known(i)) => {
                lang_item_crate!(db, cur_crate, i.ty_to_string())
            }
            TypeCtor::Str => lang_item_crate!(db, cur_crate, "str"),
            TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"),
            _ => None,
        },
        _ => None,
    }
}

/// Look up the method with the given name, returning the actual autoderefed
/// receiver type (but without autoref applied yet).
pub(crate) fn lookup_method(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    name: &Name,
    resolver: &Resolver,
) -> Option<(Ty, Function)> {
    iterate_method_candidates(ty, db, resolver, Some(name), |ty, f| Some((ty.clone(), f)))
}

// This would be nicer if it just returned an iterator, but that runs into
// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
pub(crate) fn iterate_method_candidates<T>(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    resolver: &Resolver,
    name: Option<&Name>,
    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
    // For method calls, rust first does any number of autoderef, and then one
    // autoref (i.e. when the method takes &self or &mut self). We just ignore
    // the autoref currently -- when we find a method matching the given name,
    // we assume it fits.

    // Also note that when we've got a receiver like &S, even if the method we
    // find in the end takes &self, we still do the autoderef step (just as
    // rustc does an autoderef and then autoref again).

    let krate = resolver.krate()?;
    for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
        if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback)
        {
            return Some(result);
        }
        if let Some(result) =
            iterate_trait_method_candidates(&derefed_ty, db, resolver, name, &mut callback)
        {
            return Some(result);
        }
    }
    None
}

fn iterate_trait_method_candidates<T>(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    resolver: &Resolver,
    name: Option<&Name>,
    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
    let krate = resolver.krate()?;
    // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
    let env = lower::trait_env(db, resolver);
    'traits: for t in resolver.traits_in_scope(db) {
        let data = t.trait_data(db);
        // we'll be lazy about checking whether the type implements the
        // trait, but if we find out it doesn't, we'll skip the rest of the
        // iteration
        let mut known_implemented = false;
        for item in data.items() {
            if let TraitItem::Function(m) = *item {
                let data = m.data(db);
                if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
                    if !known_implemented {
                        let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
                        if db.trait_solve(krate, goal).is_none() {
                            continue 'traits;
                        }
                    }
                    known_implemented = true;
                    if let Some(result) = callback(&ty.value, m) {
                        return Some(result);
                    }
                }
            }
        }
    }
    None
}

fn iterate_inherent_methods<T>(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    name: Option<&Name>,
    krate: Crate,
    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
    for krate in def_crates(db, krate, &ty.value)? {
        let impls = db.impls_in_crate(krate);

        for impl_block in impls.lookup_impl_blocks(&ty.value) {
            for item in impl_block.items(db) {
                if let ImplItem::Method(f) = item {
                    let data = f.data(db);
                    if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
                        if let Some(result) = callback(&ty.value, f) {
                            return Some(result);
                        }
                    }
                }
            }
        }
    }
    None
}

pub(crate) fn implements_trait(
    ty: &Canonical<Ty>,
    db: &impl HirDatabase,
    resolver: &Resolver,
    krate: Crate,
    trait_: Trait,
) -> bool {
    let env = lower::trait_env(db, resolver);
    let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
    let solution = db.trait_solve(krate, goal);

    solution.is_some()
}

impl Ty {
    // This would be nicer if it just returned an iterator, but that runs into
    // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
    pub fn iterate_impl_items<T>(
        self,
        db: &impl HirDatabase,
        krate: Crate,
        mut callback: impl FnMut(ImplItem) -> Option<T>,
    ) -> Option<T> {
        for krate in def_crates(db, krate, &self)? {
            let impls = db.impls_in_crate(krate);

            for impl_block in impls.lookup_impl_blocks(&self) {
                for item in impl_block.items(db) {
                    if let Some(result) = callback(item) {
                        return Some(result);
                    }
                }
            }
        }
        None
    }
}

/// This creates Substs for a trait with the given Self type and type variables
/// for all other parameters, to query Chalk with it.
fn generic_implements_goal(
    db: &impl HirDatabase,
    env: Arc<TraitEnvironment>,
    trait_: Trait,
    self_ty: Canonical<Ty>,
) -> Canonical<InEnvironment<super::Obligation>> {
    let mut substs = Vec::new();
    let generics = trait_.generic_params(db);
    let num_vars = self_ty.num_vars;
    substs.push(self_ty.value);
    substs.extend(
        generics
            .params_including_parent()
            .into_iter()
            .skip(1)
            .enumerate()
            .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
    );
    let num_vars = substs.len() - 1 + self_ty.num_vars;
    let trait_ref = TraitRef { trait_, substs: substs.into() };
    let obligation = super::Obligation::Trait(trait_ref);
    Canonical { num_vars, value: InEnvironment::new(env, obligation) }
}
<|endoftext|>


<commit_before>use base::world::ChunkProvider;
use ghost::Ghost;
use event_manager::{CloseHandler, EventManager, EventResponse};
use glium::backend::glutin_backend::GlutinFacade;
use glium::{self, DisplayBuild, glutin};
use super::Renderer;
use super::{Config, GameContext, WorldManager};
use base::gen::WorldGenerator;
use std::time::{Duration, Instant};
use std::rc::Rc;
use std::net::{SocketAddr, TcpStream};
use std::error::Error;
use view::SkyView;

pub struct Game {
    renderer: Renderer,
    event_manager: EventManager,
    world_manager: WorldManager,
    player: Ghost,
    #[allow(dead_code)]
    server: TcpStream,
    sky_view: SkyView,
}

impl Game {
    pub fn new(config: Config, server: SocketAddr) -> Result<Self, Box<Error>> {
        info!("connecting to {}", server);
        let server = try!(TcpStream::connect(server));
        let facade = try!(create_context(&config));
        let context = Rc::new(GameContext::new(facade, config.clone()));

        Ok(Game {
            renderer: Renderer::new(context.clone()),
            event_manager: EventManager::new(context.get_facade().clone()),
            world_manager: WorldManager::new(create_chunk_provider(context.get_config()),
                                             context.clone()),
            player: Ghost::new(context.clone()),
            server: server,
            sky_view: SkyView::new(context.clone()),
        })
    }

    /// Main game function: contains the main render loop and owns all important
    /// components. This function should remain rather small, all heavy lifting
    /// should be done in other functions.
    pub fn run(mut self) -> Result<(), Box<Error>> {
        let mut frames = 0;
        let mut next_fps_measure = Instant::now() + Duration::from_secs(1);
        let mut time_prev = Instant::now();

        loop {
            self.world_manager.update_world(self.player.get_camera().position);

            let time_now = Instant::now();
            let duration_delta = time_now.duration_since(time_prev);
            let delta = ((duration_delta.subsec_nanos() / 1_000) as f32) / 1_000_000.0 +
                        duration_delta.as_secs() as f32;

            time_prev = Instant::now();

            try!(self.renderer.render(&*self.world_manager.get_view(),
                                      &self.player.get_camera(),
                                      &self.sky_view));
            let event_resp = self.event_manager
                .poll_events(vec![&mut CloseHandler, &mut self.player]);
            if event_resp == EventResponse::Quit {
                break;
            }
            self.player.update(delta);

            frames += 1;
            if next_fps_measure < Instant::now() {
                info!("{} FPS", frames);
                next_fps_measure = Instant::now() + Duration::from_secs(1);
                frames = 0;
            }
        }

        Ok(())
    }
}

fn create_chunk_provider(config: &Config) -> Box<ChunkProvider> {
    Box::new(WorldGenerator::with_seed(config.seed))
}

/// Creates the OpenGL context and prints useful information about the
/// success or failure of said action.
fn create_context(config: &Config) -> Result<GlutinFacade, Box<Error>> {
    // Create glium context
    // TODO: handle fullscreen
    // TODO: OpenGL version/profile
    // TODO: vsync
    let context = glutin::WindowBuilder::new()
        .with_dimensions(config.resolution.width, config.resolution.height)
        .with_title(config.window_title.clone())
        .with_depth_buffer(24)
        .build_glium();

    match context {
        Err(e) => {
            // TODO: print more user friendly output
            error!("OpenGL context creation failed! Detailed error:");
            error!("{}", e);

            Err(e.into())
        }
        Ok(context) => {
            // Print some information about the acquired OpenGL context
            info!("OpenGL context was successfully built");

            let glium::Version(api, major, minor) = *context.get_opengl_version();
            info!("Version of context: {} {}.{}",
                  if api == glium::Api::Gl { "OpenGL" } else { "OpenGL ES" },
                  major,
                  minor);

            let glium::Version(api, major, minor) = context.get_supported_glsl_version();
            info!("Supported GLSL version: {} {}.{}",
                  if api == glium::Api::Gl { "GLSL" } else { "GLSL ES" },
                  major,
                  minor);

            if let Some(mem) = context.get_free_video_memory().map(|mem| mem as u64) {
                let (mem, unit) = match () {
                    _ if mem < (1 << 12) => (mem, "B"),
                    _ if mem < (1 << 22) => (mem >> 10, "KB"),
                    _ if mem < (1 << 32) => (mem >> 20, "MB"),
                    _ => (mem >> 30, "GB"),
                };
                info!("Free GPU memory (estimated): {}{}", mem, unit);
            }

            Ok(context)
        }
    }
}
<commit_msg>make use of config params for context creation (#69)<commit_after>use base::world::ChunkProvider;
use ghost::Ghost;
use event_manager::{CloseHandler, EventManager, EventResponse};
use glium::backend::glutin_backend::GlutinFacade;
use glium::{self, DisplayBuild, glutin};
use super::Renderer;
use super::{Config, GameContext, WorldManager};
use config::WindowMode;
use base::gen::WorldGenerator;
use std::time::{Duration, Instant};
use std::rc::Rc;
use std::net::{SocketAddr, TcpStream};
use std::error::Error;
use view::SkyView;

pub struct Game {
    renderer: Renderer,
    event_manager: EventManager,
    world_manager: WorldManager,
    player: Ghost,
    #[allow(dead_code)]
    server: TcpStream,
    sky_view: SkyView,
}

impl Game {
    pub fn new(config: Config, server: SocketAddr) -> Result<Self, Box<Error>> {
        info!("connecting to {}", server);
        let server = try!(TcpStream::connect(server));
        let facade = try!(create_context(&config));
        let context = Rc::new(GameContext::new(facade, config.clone()));

        Ok(Game {
            renderer: Renderer::new(context.clone()),
            event_manager: EventManager::new(context.get_facade().clone()),
            world_manager: WorldManager::new(create_chunk_provider(context.get_config()),
                                             context.clone()),
            player: Ghost::new(context.clone()),
            server: server,
            sky_view: SkyView::new(context.clone()),
        })
    }

    /// Main game function: contains the main render loop and owns all important
    /// components. This function should remain rather small, all heavy lifting
    /// should be done in other functions.
    pub fn run(mut self) -> Result<(), Box<Error>> {
        let mut frames = 0;
        let mut next_fps_measure = Instant::now() + Duration::from_secs(1);
        let mut time_prev = Instant::now();

        loop {
            self.world_manager.update_world(self.player.get_camera().position);

            let time_now = Instant::now();
            let duration_delta = time_now.duration_since(time_prev);
            let delta = ((duration_delta.subsec_nanos() / 1_000) as f32) / 1_000_000.0 +
                        duration_delta.as_secs() as f32;

            time_prev = Instant::now();

            try!(self.renderer.render(&*self.world_manager.get_view(),
                                      &self.player.get_camera(),
                                      &self.sky_view));
            let event_resp = self.event_manager
                .poll_events(vec![&mut CloseHandler, &mut self.player]);
            if event_resp == EventResponse::Quit {
                break;
            }
            self.player.update(delta);

            frames += 1;
            if next_fps_measure < Instant::now() {
                info!("{} FPS", frames);
                next_fps_measure = Instant::now() + Duration::from_secs(1);
                frames = 0;
            }
        }

        Ok(())
    }
}

fn create_chunk_provider(config: &Config) -> Box<ChunkProvider> {
    Box::new(WorldGenerator::with_seed(config.seed))
}

/// Creates the OpenGL context and prints useful information about the
/// success or failure of said action.
fn create_context(config: &Config) -> Result<GlutinFacade, Box<Error>> {
    // Create glium context
    // TODO: handle fullscreen
    // TODO: OpenGL version/profile
    // TODO: vsync
    // let context = glutin::WindowBuilder::new()
    // .with_dimensions(config.resolution.width, config.resolution.height)
    // .with_title(config.window_title.clone())
    // .with_depth_buffer(24)
    // .build_glium();

    // initialize window builder
    let mut window_builder = glutin::WindowBuilder::new();

    // check for window mode and set params
    match config.window_mode {
        WindowMode::Windowed => {
            window_builder = window_builder.with_decorations(true);
            window_builder =
                window_builder.with_dimensions(config.resolution.width, config.resolution.height);
            window_builder = window_builder.with_title(config.window_title.clone());
        }
        // FullScreenWindow => (),
        //
        // takes monitor resolution for fullscreen mode
        WindowMode::FullScreen => {
            window_builder = window_builder.with_fullscreen(glutin::get_primary_monitor());
            // TODO: Do we want native resolution for fullscreen or black bars (for
            // performance reasons)?
            // maybe remove next two lines
            window_builder =
                window_builder.with_dimensions(config.resolution.width, config.resolution.height);
        }
    }

    // check for vsync
    if config.vsync {
        window_builder = window_builder.with_vsync();
    }

    // Create glium context
    let context = window_builder.with_depth_buffer(24).build_glium();

    match context {
        Err(e) => {
            // TODO: print more user friendly output
            error!("OpenGL context creation failed! Detailed error:");
            error!("{}", e);

            Err(e.into())
        }
        Ok(context) => {
            // Print some information about the acquired OpenGL context
            info!("OpenGL context was successfully built");

            let glium::Version(api, major, minor) = *context.get_opengl_version();
            info!("Version of context: {} {}.{}",
                  if api == glium::Api::Gl { "OpenGL" } else { "OpenGL ES" },
                  major,
                  minor);

            let glium::Version(api, major, minor) = context.get_supported_glsl_version();
            info!("Supported GLSL version: {} {}.{}",
                  if api == glium::Api::Gl { "GLSL" } else { "GLSL ES" },
                  major,
                  minor);

            if let Some(mem) = context.get_free_video_memory().map(|mem| mem as u64) {
                let (mem, unit) = match () {
                    _ if mem < (1 << 12) => (mem, "B"),
                    _ if mem < (1 << 22) => (mem >> 10, "KB"),
                    _ if mem < (1 << 32) => (mem >> 20, "MB"),
                    _ => (mem >> 30, "GB"),
                };
                info!("Free GPU memory (estimated): {}{}", mem, unit);
            }

            Ok(context)
        }
    }
}
<|endoftext|>


<commit_before>use super::args::Args;
use super::index::Index;
use crate::{cmd, Command, Func};
use crate::cmd::desc::Desc;

use ql2::term::TermType;

pub trait Arg {
    fn arg(self) -> cmd::Arg<()>;
}

impl Arg for Command {
    fn arg(self) -> cmd::Arg<()> {
        Self::new(TermType::OrderBy).with_arg(self).into_arg()
    }
}

impl Arg for Desc {
    fn arg(self) -> cmd::Arg<()> {
        Command::new(TermType::OrderBy).with_arg(self.0).into_arg()
    }
}

impl<T> Arg for T
where
    T: Into<String>,
{
    fn arg(self) -> cmd::Arg<()> {
        Command::from_json(self.into()).arg()
    }
}

impl<T> Arg for Args<(T, Index)>
where
    T: Into<String>,
{
    fn arg(self) -> cmd::Arg<()> {
        let Args((key, Index(index))) = self;
        Command::from_json(key.into()).arg().with_arg(index)
    }
}

impl Arg for Func {
    fn arg(self) -> cmd::Arg<()> {
        let Func(func) = self;
        func.arg()
    }
}

impl Arg for Args<(Func, Index)> {
    fn arg(self) -> cmd::Arg<()> {
        let Args((Func(func), Index(index))) = self;
        func.arg().with_arg(index)
    }
}

impl Arg for Index {
    fn arg(self) -> cmd::Arg<()> {
        let Index(query) = self;
        query.arg()
    }
}
<commit_msg>Minor cleanup + asc implementation<commit_after>use super::args::Args;
use super::index::Index;
use ql2::term::TermType;
use crate::{
    cmd,
    cmd::{desc::Desc, asc::Asc},
    Command,
    Func
};

pub trait Arg {
    fn arg(self) -> cmd::Arg<()>;
}

impl Arg for Command {
    fn arg(self) -> cmd::Arg<()> {
        Self::new(TermType::OrderBy).with_arg(self).into_arg()
    }
}

impl Arg for Desc {
    fn arg(self) -> cmd::Arg<()> {
        Command::new(TermType::OrderBy).with_arg(self.0).into_arg()
    }
}

impl Arg for Asc {
    fn arg(self) -> cmd::Arg<()> {
        Command::new(TermType::OrderBy).with_arg(self.0).into_arg()
    }
}

impl<T> Arg for T
where
    T: Into<String>,
{
    fn arg(self) -> cmd::Arg<()> {
        Command::from_json(self.into()).arg()
    }
}

impl<T> Arg for Args<(T, Index)>
where
    T: Into<String>,
{
    fn arg(self) -> cmd::Arg<()> {
        let Args((key, Index(index))) = self;
        Command::from_json(key.into()).arg().with_arg(index)
    }
}

impl Arg for Func {
    fn arg(self) -> cmd::Arg<()> {
        let Func(func) = self;
        func.arg()
    }
}

impl Arg for Args<(Func, Index)> {
    fn arg(self) -> cmd::Arg<()> {
        let Args((Func(func), Index(index))) = self;
        func.arg().with_arg(index)
    }
}

impl Arg for Index {
    fn arg(self) -> cmd::Arg<()> {
        let Index(query) = self;
        query.arg()
    }
}
<|endoftext|>


<commit_before>use std::error::Error;

use rustc_serialize::json;
use rustc_serialize::{Decodable, Encodable};

extern crate postgres;

use self::postgres::{Connection, SslMode};

use uuid::Uuid;

pub struct Storage {
    pub connection_url: &'static str,
    pub table_name: &'static str
}

impl Storage {

    fn ensure_connection(&self) -> Result<Connection, Box<Error>> {
        let connection = try!(Connection::connect(self.connection_url, SslMode::None));
        try!(connection.execute("CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\" WITH SCHEMA public", &[]));
        try!(connection.execute(&format!(
            "CREATE TABLE IF NOT EXISTS {} (
               id uuid DEFAULT uuid_generate_v4() NOT NULL PRIMARY KEY,
               data jsonb NOT NULL
            )", &self.table_name), &[]));
        Ok(connection)
    }

    pub fn dump<T: Encodable>(&self, id: &String, storable: T) -> Result<(), Box<Error>> {
        let json: json::Json = try!(json::Json::from_str(&try!(json::encode(&storable))));
        try!(self.ensure_connection().ok().unwrap().execute(&format!("INSERT INTO {} (id, data) VALUES ($1, $2)", &self.table_name), &[&try!(Uuid::parse_str(id)), &json]));
        Ok(())
    }

    pub fn delete(&self, id: &String) -> Result<Option<()>, Box<Error>> {
        try!(self.ensure_connection().ok().unwrap().execute(&format!("DELETE FROM {} WHERE id = $1", &self.table_name), &[&try!(Uuid::parse_str(id))]));
        Ok(Some(()))
    }

    pub fn load<T: Decodable>(&self, id: &String) -> Result<Option<T>, Box<Error>> {
        let connection = self.ensure_connection().ok().unwrap();
        for row in &try!(connection.query(&format!("SELECT id, data FROM {} WHERE id = $1", &self.table_name), &[&try!(Uuid::parse_str(id))])) {
            let json: json::Json = row.get(1);
            let data: T = try!(json::decode(&json.to_string()));
            // let json = try!(json::decode(&data));
            return Ok(Some(data))
        }
        Ok(None)
    }
}
<commit_msg>Remove extra decoding.<commit_after>use std::error::Error;

use rustc_serialize::json;
use rustc_serialize::{Decodable, Encodable};

extern crate postgres;

use self::postgres::{Connection, SslMode};

use uuid::Uuid;

pub struct Storage {
    pub connection_url: &'static str,
    pub table_name: &'static str
}

impl Storage {

    fn ensure_connection(&self) -> Result<Connection, Box<Error>> {
        let connection = try!(Connection::connect(self.connection_url, SslMode::None));
        try!(connection.execute("CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\" WITH SCHEMA public", &[]));
        try!(connection.execute(&format!(
            "CREATE TABLE IF NOT EXISTS {} (
               id uuid DEFAULT uuid_generate_v4() NOT NULL PRIMARY KEY,
               data jsonb NOT NULL
            )", &self.table_name), &[]));
        Ok(connection)
    }

    pub fn dump<T: Encodable>(&self, id: &String, storable: T) -> Result<(), Box<Error>> {
        let json: json::Json = try!(json::Json::from_str(&try!(json::encode(&storable))));
        try!(self.ensure_connection().ok().unwrap().execute(&format!("INSERT INTO {} (id, data) VALUES ($1, $2)", &self.table_name), &[&try!(Uuid::parse_str(id)), &json]));
        Ok(())
    }

    pub fn delete(&self, id: &String) -> Result<Option<()>, Box<Error>> {
        try!(self.ensure_connection().ok().unwrap().execute(&format!("DELETE FROM {} WHERE id = $1", &self.table_name), &[&try!(Uuid::parse_str(id))]));
        Ok(Some(()))
    }

    pub fn load<T: Decodable>(&self, id: &String) -> Result<Option<T>, Box<Error>> {
        let connection = self.ensure_connection().ok().unwrap();
        for row in &try!(connection.query(&format!("SELECT id, data FROM {} WHERE id = $1", &self.table_name), &[&try!(Uuid::parse_str(id))])) {
            let json: json::Json = row.get(1);
            let data: T = try!(json::decode(&json.to_string()));
            return Ok(Some(data))
        }
        Ok(None)
    }
}
<|endoftext|>


<commit_before>use std::iter::range_step;
use std::iter;

pub mod graphics_sdl;

const MAX_HORIZONTAL_PIXELS : uint = 128;
const MAX_VERTICAL_PIXELS : uint = 64;

struct Dimensions {
    width:  uint,
    height: uint
}

static SCHIP_DIMENSIONS :Dimensions = Dimensions{ width: 128, height: 64};
static  CHIP_DIMENSIONS :Dimensions = Dimensions{ width: 64,  height: 32};

// Enums are uncopyable wtf, now completely useless >.>
// Use bools instead to check CHIP or SCHIP mode
fn get_width(mode : bool) -> uint {
    match mode {
        false => CHIP_DIMENSIONS.width,
        true => SCHIP_DIMENSIONS.width
    }
}

fn get_height(mode : bool) -> uint {
    match mode {
        false => CHIP_DIMENSIONS.height,
        true => SCHIP_DIMENSIONS.height
    }
}

pub struct Graphics {
    mode :bool,
    screen : [[bool; MAX_HORIZONTAL_PIXELS]; MAX_VERTICAL_PIXELS],
    out : graphics_sdl::Screen
}

impl Graphics {

    pub fn new() -> Graphics {
        Graphics { mode: false,
                   /* Initialize all pixels to blank */
                   screen: [[false; MAX_HORIZONTAL_PIXELS]; MAX_VERTICAL_PIXELS],
                   out: graphics_sdl::Screen::new(256, 128,
                    CHIP_DIMENSIONS.width, CHIP_DIMENSIONS.height)
         }
    }

    pub fn set_mode(&mut self, new_mode:bool) {
        self.mode = new_mode;
        self.out.set_x_max(get_width(new_mode));
        self.out.set_y_max(get_height(new_mode));
    }

    pub fn draw_pix(&mut self, x:uint, y:uint, state:bool) {
        self.screen[y][x] = state;
    }

    /* Create a bit vector for the supplied number from
     * MS bit to LS bit */
    fn to_bit_vec(n:uint, bit_count:uint) -> Vec<u8> {

        let largest_bit : uint = 1 << (bit_count - 1);

        iter::range(0, bit_count)
            .map(|idx| if n & (largest_bit >> idx ) != 0 {1u8} else {0u8})
            .collect()
    }

    pub fn draw_line(&mut self, startx:u8, starty:u8, line:uint, bits:uint) -> bool {

       let mut unset_occured = false;

       let  pixel_states :Vec<bool>  = Graphics::to_bit_vec(line, bits)
                       .iter()
                       .map(|&x| if x == 0 {false} else {true})
                       .collect();

        let current_states = self.screen[starty as uint]
                        .slice_from_mut(startx as uint);

        let mut zipped_states = current_states.iter_mut().zip(pixel_states.iter());
        /* Set pixel to old pixel xor new pixel */
        for (old, new) in zipped_states {
            if !unset_occured && *old == true && *new == true {
                unset_occured = true;
            }
            *old = *old ^ *new;
        }

        return unset_occured;;
   }

    pub fn scroll_right(&mut self, n:u8) {
        let n = n as uint;
        for y in range(0, get_height(self.mode)) {
            for x in range_step(get_width(self.mode) - 1, n  - 1, -1) {
                let set = self.screen[y][x - n];
                self.draw_pix(x, y, set);
            }
            for x  in range(0, n) {
                self.draw_pix(x, y, false);
            }
        }
    }

    pub fn scroll_left(&mut self, n:u8) {
        let x_max = get_width(self.mode);
        let n = n as uint;
        for y in range(0 , get_height(self.mode)) {
            for x in range(0, x_max - n) {
                let set = self.screen[y][x + n];
                self.draw_pix(x, y, set);
            }
            for x in range(x_max - n, x_max) {
                self.draw_pix(x, y, false);
            }
        }
    }

    pub fn scroll_down(&mut self, n:u8) {
        let y_max = get_height(self.mode);
        let n = n as uint;
        for x in range(0, get_width(self.mode)) {
            for y in range_step(y_max - 1, n - 1, -1) {
                let set = self.screen[y - n][x];
                self.draw_pix(x, y, set);
            }
            for y  in range(0, n) {
                self.draw_pix(x, y, false);
            }
        }
    }

    pub fn clear_screen(&mut self) {
        for y in range(0, MAX_VERTICAL_PIXELS) {
            for x in range(0, MAX_HORIZONTAL_PIXELS) {
                self.screen[y][x] = false;
            }
        }
        self.out.clear_screen();
    }

    //TODO improve as iinefficient (causes redrawing of entire screen)
    pub fn show(&mut self) {
        for y in range(0, MAX_VERTICAL_PIXELS) {
            for x in range(0, MAX_HORIZONTAL_PIXELS) {
                self.out.draw_pix(x as int, y as int, self.screen[y][x]);
            }
        }
        self.out.show();
    }
}
<commit_msg>Fixed bug in drawing when attempting to draw out of bounds<commit_after>use std::iter::range_step;
use std::iter;

pub mod graphics_sdl;

const MAX_HORIZONTAL_PIXELS : uint = 128;
const MAX_VERTICAL_PIXELS : uint = 64;

struct Dimensions {
    width:  uint,
    height: uint
}

static SCHIP_DIMENSIONS :Dimensions = Dimensions{ width: 128, height: 64};
static  CHIP_DIMENSIONS :Dimensions = Dimensions{ width: 64,  height: 32};

// Enums are uncopyable wtf, now completely useless >.>
// Use bools instead to check CHIP or SCHIP mode
fn get_width(mode : bool) -> uint {
    match mode {
        false => CHIP_DIMENSIONS.width,
        true => SCHIP_DIMENSIONS.width
    }
}

fn get_height(mode : bool) -> uint {
    match mode {
        false => CHIP_DIMENSIONS.height,
        true => SCHIP_DIMENSIONS.height
    }
}

pub struct Graphics {
    mode :bool,
    screen : [[bool; MAX_HORIZONTAL_PIXELS]; MAX_VERTICAL_PIXELS],
    out : graphics_sdl::Screen
}

impl Graphics {

    pub fn new() -> Graphics {
        Graphics { mode: false,
                   /* Initialize all pixels to blank */
                   screen: [[false; MAX_HORIZONTAL_PIXELS]; MAX_VERTICAL_PIXELS],
                   out: graphics_sdl::Screen::new(256, 128,
                    CHIP_DIMENSIONS.width, CHIP_DIMENSIONS.height)
         }
    }

    pub fn set_mode(&mut self, new_mode:bool) {
        self.mode = new_mode;
        self.out.set_x_max(get_width(new_mode));
        self.out.set_y_max(get_height(new_mode));
    }

    pub fn draw_pix(&mut self, x:uint, y:uint, state:bool) {
        self.screen[y][x] = state;
    }

    /* Create a bit vector for the supplied number from
     * MS bit to LS bit */
    fn to_bit_vec(n:uint, bit_count:uint) -> Vec<u8> {

        let largest_bit : uint = 1 << (bit_count - 1);

        iter::range(0, bit_count)
            .map(|idx| if n & (largest_bit >> idx ) != 0 {1u8} else {0u8})
            .collect()
    }

    pub fn draw_line(&mut self, startx:u8, starty:u8, line:uint, bits:uint) -> bool {

       let mut unset_occured = false;

       let  pixel_states :Vec<bool>  = Graphics::to_bit_vec(line, bits)
                       .iter()
                       .map(|&x| if x == 0 {false} else {true})
                       .collect();

        let current_states = self.screen[starty as uint % 64]
                        .slice_from_mut(startx as uint);

        let mut zipped_states = current_states.iter_mut().zip(pixel_states.iter());
        /* Set pixel to old pixel xor new pixel */
        for (old, new) in zipped_states {
            if !unset_occured && *old == true && *new == true {
                unset_occured = true;
            }
            *old = *old ^ *new;
        }

        return unset_occured;;
   }

    pub fn scroll_right(&mut self, n:u8) {
        let n = n as uint;
        for y in range(0, get_height(self.mode)) {
            for x in range_step(get_width(self.mode) - 1, n  - 1, -1) {
                let set = self.screen[y][x - n];
                self.draw_pix(x, y, set);
            }
            for x  in range(0, n) {
                self.draw_pix(x, y, false);
            }
        }
    }

    pub fn scroll_left(&mut self, n:u8) {
        let x_max = get_width(self.mode);
        let n = n as uint;
        for y in range(0 , get_height(self.mode)) {
            for x in range(0, x_max - n) {
                let set = self.screen[y][x + n];
                self.draw_pix(x, y, set);
            }
            for x in range(x_max - n, x_max) {
                self.draw_pix(x, y, false);
            }
        }
    }

    pub fn scroll_down(&mut self, n:u8) {
        let y_max = get_height(self.mode);
        let n = n as uint;
        for x in range(0, get_width(self.mode)) {
            for y in range_step(y_max - 1, n - 1, -1) {
                let set = self.screen[y - n][x];
                self.draw_pix(x, y, set);
            }
            for y  in range(0, n) {
                self.draw_pix(x, y, false);
            }
        }
    }

    pub fn clear_screen(&mut self) {
        for y in range(0, MAX_VERTICAL_PIXELS) {
            for x in range(0, MAX_HORIZONTAL_PIXELS) {
                self.screen[y][x] = false;
            }
        }
        self.out.clear_screen();
    }

    //TODO improve as iinefficient (causes redrawing of entire screen)
    pub fn show(&mut self) {
        for y in range(0, MAX_VERTICAL_PIXELS) {
            for x in range(0, MAX_HORIZONTAL_PIXELS) {
                self.out.draw_pix(x as int, y as int, self.screen[y][x]);
            }
        }
        self.out.show();
    }
}
<|endoftext|>


<commit_before>use bot::BotEnv;
use tasks::{RunsTask, Wait};
use chrono::prelude::*;
use chrono::Duration;
use database::models::Timeout;

use serenity::model::id::GuildId;

use diesel::prelude::*;

use std::sync::Arc;
use std::thread;

pub struct TimeoutCheckTask {
  next_sleep: i64
}

impl TimeoutCheckTask {
  pub fn new() -> TimeoutCheckTask {
    TimeoutCheckTask {
      next_sleep: 0
    }
  }
}

pub fn remove_timeout(timeout: &Timeout) {
  let mut member = match GuildId(*timeout.server_id).member(*timeout.user_id) {
    Ok(m) => m,
    Err(e) => {
      warn!("could not get member for timeout check: {}", e);
      return;
    }
  };
  if let Err(e) = member.remove_role(*timeout.role_id) {
    warn!("could not remove timeout role from {}: {}", *timeout.user_id, e);
  }
  if let Err(e) = ::bot::with_connection(|c| ::diesel::delete(timeout).execute(c)) {
    warn!("could not delete timeout {}: {}", timeout.id, e);
  }
}

impl RunsTask for TimeoutCheckTask {
  fn start(mut self, env: Arc<BotEnv>) {
    loop {
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      let now = Utc::now();
      let next_five_minutes = (now + Duration::minutes(5)).timestamp();
      let mut timeouts: Vec<Timeout> = match ::bot::with_connection(|c| ::database::schema::timeouts::dsl::timeouts.load(c)) {
        Ok(t) => t,
        Err(e) => {
          warn!("could not load timeouts: {}", e);
          continue;
        }
      };
      timeouts.retain(|t| t.ends() <= next_five_minutes);

      if timeouts.is_empty() {
        continue;
      }

      ::std::thread::spawn(move || {
        for (wait, timeout) in Wait::new(timeouts.into_iter().map(|t| (t.ends(), t))) {
          ::std::thread::sleep(Duration::seconds(wait).to_std().unwrap());
          remove_timeout(&timeout);
        }
      });
      self.next_sleep = env.config.read().timeouts.role_check_interval.unwrap_or(300);
    }
  }
}
<commit_msg>fix: always set next_sleep before possible continues<commit_after>use bot::BotEnv;
use tasks::{RunsTask, Wait};
use chrono::prelude::*;
use chrono::Duration;
use database::models::Timeout;

use serenity::model::id::GuildId;

use diesel::prelude::*;

use std::sync::Arc;
use std::thread;

#[derive(Default)]
pub struct TimeoutCheckTask {
  next_sleep: i64
}

pub fn remove_timeout(timeout: &Timeout) {
  let mut member = match GuildId(*timeout.server_id).member(*timeout.user_id) {
    Ok(m) => m,
    Err(e) => {
      warn!("could not get member for timeout check: {}", e);
      return;
    }
  };
  if let Err(e) = member.remove_role(*timeout.role_id) {
    warn!("could not remove timeout role from {}: {}", *timeout.user_id, e);
  }
  if let Err(e) = ::bot::with_connection(|c| ::diesel::delete(timeout).execute(c)) {
    warn!("could not delete timeout {}: {}", timeout.id, e);
  }
}

impl RunsTask for TimeoutCheckTask {
  fn start(mut self, env: Arc<BotEnv>) {
    loop {
      thread::sleep(Duration::seconds(self.next_sleep).to_std().unwrap());
      if self.next_sleep == 0 {
        self.next_sleep = env.config.read().timeouts.role_check_interval.unwrap_or(300);
      }
      let now = Utc::now();
      let next_five_minutes = (now + Duration::minutes(5)).timestamp();
      let mut timeouts: Vec<Timeout> = match ::bot::with_connection(|c| ::database::schema::timeouts::dsl::timeouts.load(c)) {
        Ok(t) => t,
        Err(e) => {
          warn!("could not load timeouts: {}", e);
          continue;
        }
      };
      timeouts.retain(|t| t.ends() <= next_five_minutes);

      if timeouts.is_empty() {
        continue;
      }

      ::std::thread::spawn(move || {
        for (wait, timeout) in Wait::new(timeouts.into_iter().map(|t| (t.ends(), t))) {
          ::std::thread::sleep(Duration::seconds(wait).to_std().unwrap());
          remove_timeout(&timeout);
        }
      });
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(nll)]

// test for https://github.com/rust-lang/rust/issues/29723

fn main() {
    let s = String::new();
    let _s = match 0 {
        0 if { drop(s); false } => String::from("oops"),
        _ => {
            // This should trigger an error,
            // s could have been moved from.
            s
        }
    };
}
<commit_msg>add ERROR annotation<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(nll)]

// test for https://github.com/rust-lang/rust/issues/29723

fn main() {
    let s = String::new();
    let _s = match 0 {
        0 if { drop(s); false } => String::from("oops"),
        _ => {
            // This should trigger an error,
            // s could have been moved from.
            s
            //~ ERROR use of moved value: `s`
        }
    };
}
<|endoftext|>